manejo - que es un control en c#
Cree manejadores de eventos C#vacíos automáticamente (8)
En C # 6.0, no es necesario ir a ninguna de estas longitudes para realizar la comprobación nula, gracias al operador nulo condicional ?.
Los documentos explican que llamar a MyEvent?.Invoke(...)
copia el evento en una variable temporal, realiza la comprobación nula y, si no es nula, llama a Invoke
en la copia temporal. Esto no es necesariamente seguro para subprocesos en todos los sentidos, ya que alguien podría haber agregado un nuevo evento después de la copia a la variable temporal, que no se llamaría. Sin embargo, garantiza que no llamarás a Invoke
en nulo.
En breve:
public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click;
public void DoSomething() {
Click?.Invoke(this, "foo");
}
No es posible desencadenar un evento en C # que no tenga controladores asociados. Entonces, antes de cada llamada, es necesario verificar si el evento es nulo.
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
Me gustaría mantener mi código lo más limpio posible y deshacerme de esos controles nulos. No creo que afecte mucho el rendimiento, al menos no en mi caso.
MyEvent( param1, param2 );
Ahora mismo resuelvo esto agregando un controlador en línea vacío a cada evento de forma manual. Esto es propenso a errores, ya que debo recordar hacer eso, etc.
void Initialize() {
MyEvent += new MyEvent( (p1,p2) => { } );
}
¿Hay alguna manera de generar manejadores vacíos para todos los eventos de una clase determinada de forma automática utilizando reflexión y algo de magia CLR?
Esta es una mala idea porque el código que está consumiendo el evento ahora tiene una expectativa de que el objeto con el evento haya sido codificado con una acción por defecto. Si nadie va a utilizar su código en ningún otro lugar, supongo que puede salirse con la suya.
La notación:
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
no es seguro para subprocesos Deberías hacerlo de esta manera:
EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }
Entiendo que esto es una molestia, entonces puedes hacer el método de ayuda:
static void RaiseEvent( EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
y luego llama:
RaiseEvent( MyEvent, param1, param2 );
Si está utilizando C # 3.0, puede declarar el método de ayuda como método de extensión:
static void Raise( this EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
y luego llama:
MyEvent.Raise( param1, param2 );
También puede crear los siguientes métodos de extensión / ayuda para otros manejadores de eventos. Por ejemplo:
static void Raise<TEventArgs>( this EventHandler<TEventArgs> handler,
object sender, TEventArgs e ) where TEventArgs : EventArgs
{
if ( null != handler ) { handler( sender, e ); }
}
Las declaraciones de eventos C # lamentablemente incluyen una serie de problemas de seguridad e ineficiencias bien conocidos. Diseñé una serie de métodos de extensión en los delegados para invocarlos de forma segura y para registrar / anular el registro de delegados de una manera segura para subprocesos .
Su antiguo código de generación de eventos:
if (someDelegate != null) someDelegate(x, y, z);
Tu nuevo código:
someDelegate.Raise(x, y, z);
Su antiguo código de registro de evento:
event Action fooEvent;
...
lock (someDummyObject) fooEvent += newHandler;
Tu nuevo código:
Action fooEvent;
...
Events.Add(ref fooEvent, newHandler);
No se necesita bloqueo, no hay objetos ficticios insertados en el compilador utilizados para bloquear los eventos.
No necesita varios métodos de extensión para diferentes manejadores de eventos, solo necesita uno:
public static class EventHandlerExtensions {
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs {
if (handler != null) handler(sender, args);
}
}
Puedes escribir es como:
MyEvent += delegate { };
No estoy seguro de qué es lo que quieres hacer es correcto.
Puedes usar PostSharp para agregar el tiempo de compilación a esta magia. Es la mejor manera.
Vi esto en otra publicación y lo he robado descaradamente y lo he usado en gran parte de mi código desde entonces:
public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!
//Let you do this:
public void DoSomething() {
Click(this, "foo");
}
//Instead of this:
public void DoSomething() {
if (Click != null) // Unnecessary!
Click(this, "foo");
}
* Si alguien conoce el origen de esta técnica, publíquela en los comentarios. Realmente creo en la fuente obteniendo el debido crédito.
( Editar: Lo obtuve de esta publicación Características ocultas de C #? )