12
votes

Meilleure pratique en déclarant des événements en C #

Je sais que les deux méthodes suivantes fonctionnent, mais je me demande si on est mieux en termes de performance / de maintenance / peu importe.

Le brèves: p>

  private EventHandler _myEvent;
  public event EventHandler MyEvent
  {
     add { _myEvent += value; }
     remove { _myEvent -= value; }
  }


5 commentaires

Pourquoi les propriétés automatiques sont-elles mauvaises?


Peut-être parce que je suis paresseux, mais j'irais toujours pour la version courte :)


Mon premier conseil est que le court chemin est plus que suffisant pour la majorité des cas. Le long chemin est nécessaire lorsque vous en avez besoin, c'est-à-dire. Vous devez faire des choses supplémentaires lorsque des événements sont enregistrés ou non.


@Lews: Je ne veux pas dire des propriétés automatiques, mais des membres du public. Ex: Public int numéro; est une mauvaise pratique. Public int Number {Obtenir; ensemble; } n'est pas.


Parfois, avoir le délégué actuel est également nécessaire pour le débogage, l'élimination de la liste d'envoi, etc.


3 Réponses :


5
votes

Le premier moyen fait exactement le même dessous avec la création de EventHandler avec le nom MyEvent . Lorsqu'il est accessible au sein du gestionnaire d'événements de classe est renvoyé (c'est-à-dire aucun problème avec le délégué appelant) lorsqu'il est appelé à l'extérieur de la classe ( myClassInstance.myevent + = quelqu'un / myClassInstance.myevent - = SemanHlerler ) Ajouter / Supprimer Les méthodes sont appelées respectivement. Et ces méthodes sont les mêmes (sauf qu'ils ajoutent de la sécurité de thread) comme celles que vous avez écrites dans la deuxième manière.

Alors, pourquoi voulez-vous écrire plus de code lorsque vous n'en avez pas besoin?


1 commentaires

En fait, ils ne sont pas toutaux; Le compilateur comprend la sécurité du thread pour l'exemple d'événement de type champ (le premier)



29
votes

Dans ce cas, l'argument de "bonnes pratiques" est un peu plus rapide; Le premier est un "événement de type champ"; Vous notez:

Le long chemin semble similaire à l'encapsulation des membres avec des propriétés,

mais: ceci est encapsulé (derrière Ajouter / supprimer ) de chaque sens; Donc, par comparaison avec les propriétés, c'est vraiment la différence entre: xxx

et xxx

auquel cas je dirais "Utilisez le premier sauf si vous avez une raison réelle de ne pas" - il est toujours caché derrière les accesseurs. De plus, il est important de noter que votre deuxième exemple est non quel événement de type champ (le premier exemple) se développe à: le compilateur ajoute la sécurité du thread dans le mélange. Donc: je dirais utiliser le premier échantillon: xxx

Notez que "comment" pour la sécurité de thread-Safety dépend de quelle version du compilateur (et en effet, quelle spécification) que vous utilisez. . Dans les compilateurs récents de Microsoft C #, cela correspond à celui-ci avec les opérations interlocked ( comparaisonxchange etc.), de sorte qu'il ne nécessite pas d'objet de synchronisation privé dédié.


0 commentaires

1
votes

Pour vérifier ce que Marc Gravel signifie, j'ai essayé le code suivant:

private EventHandler _myEventShortWay;

public event EventHandler MyEventShortWay
    {
        add
        {
            EventHandler handler2;
            EventHandler myEventShortWay = this._myEventShortWay;
            do
            {
                handler2 = myEventShortWay;
                EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
                myEventShortWay = Interlocked.CompareExchange<EventHandler>(ref this._myEventShortWay, handler3, handler2);
            }
            while (myEventShortWay != handler2);
        }
        remove
        {
            EventHandler handler2;
            EventHandler myEventShortWay = this._myEventShortWay;
            do
            {
                handler2 = myEventShortWay;
                EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
                myEventShortWay = Interlocked.CompareExchange<EventHandler>(ref this._myEventShortWay, handler3, handler2);
            }
            while (myEventShortWay != handler2);
        }
    }

    private EventHandler _myEvent;

    public event EventHandler MyEventLongWay
    {
        add
        {
            this._myEvent = (EventHandler) Delegate.Combine(this._myEvent, value);
        }
        remove
        {
            this._myEvent = (EventHandler)Delegate.Remove(this._myEvent, value);
        }

    }


0 commentaires