68 votes

Créer automatiquement des gestionnaires d'événements C # vides

Il n'est pas possible de déclencher un événement en C# qui n'a pas de gestionnaires attaché à elle. Donc, avant chaque appel, il est nécessaire de vérifier si l'événement est nulle.

if ( MyEvent != null ) {
  MyEvent( param1, param2 );
}

Je tiens à garder mon code aussi propre que possible et de se débarrasser de ceux null contrôles. Je ne pense pas que cela affectera les performances très bien, au moins pas dans mon cas.

MyEvent( param1, param2 );

Droit maintenant, je résoudre ce problème en ajoutant un vide inline gestionnaire pour chaque événement manuellement. C'est sujette aux erreurs, car j'ai besoin de vous rappeler de le faire.

void Initialize() {
  MyEvent += new MyEvent( (p1,p2) => { } );
}

Est-il un moyen de générer du vide des gestionnaires pour tous les événements d'une classe donnée automatiquement à l'aide de la réflexion et de certains CLR de la magie?

145voto

Dinah Points 15711

Je l'ai vu sur un autre post et je l'ai volé sans vergogne et utilisé dans une grande partie de mon code depuis:

 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 quelqu'un connaît l'origine de cette technique, merci de l'afficher dans les commentaires. Je crois vraiment que la source obtiendra un crédit.

( Edit: je l'ai eu de ce post Fonctionnalités cachées de C #? )

58voto

TcKs Points 13249

La notation:

if ( MyEvent != null ) {
  MyEvent( param1, param2 );
}

n'est pas thread-safe. Vous devriez le faire de cette façon:

EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }

Je comprends que c'est pas la peine, de sorte que vous pouvez faire de la méthode d'assistance:

static void RaiseEvent( EventHandler handler, object sender, EventArgs e ) {
    if ( null != handler ) { handler( sender, e ); }
}

et puis, composez le:

RaiseEvent( MyEvent, param1, param2 );

Si vous êtes à l'aide de C# 3.0, vous pouvez déclarer la méthode d'assistance que l'extension de la méthode:

static void Raise( this EventHandler handler, object sender, EventArgs e ) {
    if ( null != handler ) { handler( sender, e ); }
}

et puis, composez le:

MyEvent.Raise( param1, param2 );

Vous pouvez aussi créer la prochaine extension/méthodes d'aide pour d'autres gestionnaires d'événements. Par exemple:

static void Raise<TEventArgs>( this EventHandler<TEventArgs> handler,
    object sender, TEventArgs e ) where TEventArgs : EventArgs
{
    if ( null != handler ) { handler( sender, e ); }
}

6voto

leppie Points 67289

Vous pouvez écrire est comme:

 MyEvent += delegate { };
 

Je ne suis pas sûr que ce que vous voulez faire est correct.

5voto

vkelman Points 76

Vous n'avez pas besoin de plusieurs méthodes d'extension pour différents gestionnaires d'événements, vous avez juste besoin d'une:

 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);
  }
}
 

2voto

mcintyre321 Points 5393

C'est une mauvaise idée car le code qui consomme l'événement suppose maintenant que l'objet avec l'événement a été codé avec une action par défaut. Si votre code ne sera jamais utilisé nulle part ailleurs par quelqu'un d'autre, alors je suppose que vous pouvez vous en tirer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X