c# - teclado - que es un evento en programacion
¿Por qué los manejadores de eventos siempre tienen un tipo de retorno de vacío? (10)
Aparte del hecho de que .NET espera una cierta firma para los eventos en los controles estándar, considere esto: un evento puede tener múltiples manejadores de eventos adjuntos, ¿cuál de los valores de retorno se usaría?
Simplemente no tiene sentido que los manejadores de eventos devuelvan un valor. Por lo general, modificarán el estado de algún objeto que se deriva de EventArgs
para comunicar algo a lo que sea que haya disparado el evento.
Oye, me preguntaba por qué es que el tipo de retorno de eventos como
private void button1_Click(object sender, EventArgs e)
siempre es nulo?
¿Puede devolver cualquier otro valor también?
Como un profesor universitario mío solía decir sobre casi todas las preguntas "Depende de la implementación". En este caso particular, al trabajar con controladores de eventos, no hay nada implícito en este modelo que impida y aplique este patrón para devolver algo al código de llamada. Sin embargo, le pasamos tanto el objeto emisor como los argumentos del evento de origen, básicamente forma el contexto del entorno de ejecución, no hay necesidad de devolver nada, ya que puede trabajar directamente con esas referencias para lograr cualquier funcionalidad relevante.
Otros marcos pueden permitir que un controlador de eventos devuelva algo.
Como varias personas ya han declarado esto, una convención no es una restricción. Puede hacer que un evento devuelva cosas dentro de EventArgs. Microsoft usa este patrón en muchos lugares; consulte el evento FormClosing en WinForms. Entonces, si quiere devolver un valor, haga algo como lo siguiente:
public class AllowCloseEventArgs : EventArgs
{
public bool AllowClose = true;
}
public void AllowClose(object sender, AllowCloseEventArgs e)
{ e.AllowClose = false; }
Sabiendo esto ahora vamos a discutir por qué los diseñadores eligieron el prototipo de evento void-return ''estándar'':
- Si tuvieran un valor de retorno, ¿qué tipo sería?
- Si el evento arrojó un valor, ¿qué significaría ese valor?
- Al no tener un tipo de devolución, los eventos pueden ser unidireccionales. Es decir, si no me importan las excepciones, puedo "disparar y olvidar" el evento como llamar a Control.BeginInvoke (...)
Actualización: Ben agrega con razón: # 4: ¿qué pasa si un evento necesita devolver más de un valor?
El tipo de devolución es nulo porque es una sub rutina, no una función. Puede hacer que devuelva un valor, pero los controladores de eventos (que es a lo que se suma un evento de sub-rutina conectado a un clic de botón) no están destinados exactamente a.
En VB, esta línea de código sería:
Private Sub button_Click(ByVal sender As Object, ByVal e As EventArgs)
La declaración "Sub" explícita en VB tiene un poco más de sentido en este caso, pero recuerde, todos los void
en C # son solo subrutinas ... hacen algo en el código basado en argumentos pero no devuelven un valor. Sin embargo, pueden cambiar los valores de los argumentos pasados.
En c #, los eventos pueden ser de dos tipos
1. Multidifusión
2. UnitCast
Evento de multidifusión son aquellos que tienen más de un suscriptor. cuando se genera un evento de multidifusión, se invoca el controlador múltiple porque se ha suscrito a más de un controlador de eventos. Por lo tanto, el evento de multidifusión está destinado a utilizarse para llamar a múltiples controladores y el controlador de multidifusión no puede tener el tipo de retorno ¿por qué?
porque si el delegado de multidifusión tiene un tipo de retorno, entonces cada controlador de eventos devolverá algún valor y el valor de retorno de un controlador de eventos será reemplazado por el siguiente valor del controlador de eventos.
supongamos que tiene un delegado de multidifusión como sigue
public delegate int buttonClick;
public event buttonClick onClick;
onClick += method1
onclick += method2
onclick += metho3
cuando se genere este evento, el valor devuelto por el método1 se reemplazará por el valor devuelto por el método2 y, finalmente, se recibirá el valor del único método3.
Por lo tanto, en el caso de un delegado de multidifusión, siempre se recomienda no devolver ningún valor.
pero en el caso de un delegado de unidifusión en el que solo tendría un suscriptor. Entonces puedes devolver valor para cumplir tu propósito
Entonces, para delegado de multidifusión - Sin tipo de retorno y para delegado de unidifusión - puede tener tipo de retorno
El delegado de multidifusión también puede devolver varios valores, pero para ese evento se debe generar manualmente.
Evento en caso de que opte por que el delegado de multidifusión también devuelva valores, digamos que estoy teniendo un evento que se vincula al controlador de eventos 4 y toma dos enteros y un controlador agrega, la segunda resta y la tercera multiplicación y la última división. Entonces, si desea obtener el tipo de devolución de todos los manejadores, entonces debe plantear el evento manualmente de la siguiente manera:
var handler = _eventToRaised.GetInvocationList();
foreach(var handler in handlers)
{
if(handler != null)
{
var returnValue = handler()// pass the values which delegate expects.
}
}
No puede hacer esto porque el delegado que maneja el evento espera una determinada firma (obtendrá un error de compilación si lo intenta y lo modifica). Por ejemplo, el delegado en este caso ( Button.Click
) es un System.EventHandler
, tiene que hacer coincidir esa firma para compilar / funcionar como un delegado en absoluto:
public delegate void EventHandler(Object sender, EventArgs e)
Así es como funcionan los delegados, cuando observas cómo se usa habitualmente , tiene más sentido:
MyButton.Click += button1_Click;
Si devolvió algo más ... ¿para qué se usaría? Si tiene la intención de llamar a algo que devuelve un resultado ... para eso es un método, no un EventHandler :)
Por supuesto, los eventos pueden devolver valores.
[TestClass]
public class UnitTest1 {
delegate int EventWithReturnValue();
class A {
public event EventWithReturnValue SomeEvent;
public int LastEventResult { get; set; }
public void RaiseEvent() {
LastEventResult = SomeEvent();
}
}
[TestMethod]
public void TestMethod1() {
A a = new A();
a.SomeEvent += new EventWithReturnValue(a_SomeEvent);
a.RaiseEvent();
Assert.AreEqual(123, a.LastEventResult);
}
int a_SomeEvent() {
return 123;
}
}
Sin embargo, no es muy común utilizar el valor de retorno de eventos para intercambiar información entre los componentes y sus consumidores.
Un evento puede tener un valor de retorno. Pero es una guía BCL para devolver el vacío (y tener 2 parámetros).
Devolver un valor se vuelve un poco confuso cuando usa la propiedad de multidifusión de eventos. El valor devuelto es el valor del último controlador ejecutado. Se pierde el retorno de todos los demás manipuladores suscritos, y como los eventos se usan para el desacoplamiento, no tiene mucho control sobre el orden en que se ejecutan. Esto hace que un valor de retorno sea muy poco práctico.
Otra práctica de BCL es compartir y devolver información a través de una propiedad de escritura de un descendiente EventArgs, por ejemplo, la propiedad Cancel
del evento Window.Closing. Todos los controladores pueden ver y cambiar esto. Sigue siendo la última solución, pero mejor.
Pero habiendo dicho todo eso, aún puedes escribir:
delegate int Summer(int[] arr); // delegate
class Program
{
public event Summer OnSum; // event
void DoSum()
{
int[] data = {1, 2, 3} ;
int sum = 0;
if (OnSum != null)
sum = OnSum(data); // execute it.
}
}
Una firma de controlador de eventos, que es el tipo de devolución y el número y tipo de argumentos que toma, está determinada por la firma del delegate
utilizado para definir el evento. Por lo tanto, el evento Click del botón en su ejemplo no admite ningún valor de retorno.
Normalmente, no esperaría devolver un valor de un controlador de eventos como valor de retorno de función porque un evento puede tener múltiples suscriptores y cada uno devolvería un valor de retorno independientemente de los otros manejadores y requeriría un código de activación de evento especial para decidir qué hacer con todos los valores de retorno.
Normalmente, si necesita comunicarse desde un controlador de eventos, la estructura EventArgs contendría miembros que el controlador puede actualizar y cada controlador tendrá la oportunidad de ver los valores y actualizarlos en consecuencia, y el código que activa el evento solo debe reaccionar a el valor final en la estructura.
el delegado de EventHandler predeterminado definió esta firma. Sin embargo, puede crear sus propios eventos con sus propios tipos de devolución si lo desea.
public class AnEvent
{
public delegate MyReturnType MyDelegateName();
public event MyDelegateName MyEvent;
public void DoStuff()
{
MyReturnType result = null;
if (MyEvent != null)
result = MyEvent();
Console.WriteLine("the event was fired");
if (result != null)
Console.Writeline("the result is" + result.ToString());
}
}
public class EventListener
{
public EventListener()
{
var anEvent = new AnEvent();
anEvent.MyEvent += SomeMethod;
}
public MyReturnType SomeMethod()
{
Console.Writeline("the event was handled!");
return new MyReturnType;
}
}