377 votes

Quelles sont les différences entre les délégués et les événements?

Quelles sont les différences entre les délégués et les événements? Ne pas tous les deux contenir des références à des fonctions qui peuvent être exécutées?

336voto

Simucal Points 34961

Une déclaration d' événement ajoute une couche d'abstraction et de protection sur l'instance de délégué . Cette protection empêche les clients du délégué de réinitialiser le délégué et sa liste d'appel et autorise uniquement l'ajout ou la suppression de cibles de la liste d'appel.

150voto

faby Points 2182

pour comprendre les différences, vous pouvez regarder cette 2 exemples

Exemple avec les Délégués (Action, dans ce cas, c'est une sorte de délégué qui ne débite pas de valeur de retour)

public class Animal
{
    public Action Run {get; set;}

    public void RaiseEvent()
    {
        if (Run != null)
        {
            Run();
        }
    }
}

pour utiliser le délégué, vous devriez faire quelque chose comme ceci

Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();

ce code fonctionne bien, mais vous pourriez avoir quelques points faibles.

Par exemple si j'écris ce

animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;

avec la dernière ligne de code que j'ai dû remplacer les comportements précédents, avec juste un manque + (j'ai utilisé l' + au lieu de +=)

Un autre point faible est que chaque classe qui utilisent votre Animal classe peut soulever RaiseEvent seulement en l'appelant animal.RaiseEvent().

Pour éviter cela, des points faibles, vous pouvez utiliser events en c#.

Votre Animal de la classe va changer de cette façon

public class ArgsSpecial :EventArgs
   {
        public ArgsSpecial (string val)
        {
            Operation=val;
        }

        public string Operation {get; set;}
   } 



 public class Animal
    {
       public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it

       public void RaiseEvent()
       {  
          Run(this, new ArgsSpecial("Run faster"));
       }
    }

pour les événements d'appels

 Animale animal= new Animal();
 animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation );
 animal.RaiseEvent();

Différences:

  1. Vous n'êtes pas à l'aide d'une propriété publique, mais un champ public (avec des événements le compilateur protéger les champs contre les accès non autorisés)
  2. Événements ne peuvent pas être directement affectés. Dans ce cas, vous ne pouvez pas faire l'erreur précédente que je vous l'ai montré substituer le comportement.
  3. Personne en dehors de votre classe peut déclencher l'événement.
  4. Les événements peuvent être inclus dans une déclaration d'interface, alors qu'un champ ne peut pas

notes

Ce gestionnaire est déclaré en tant que délégué suivant:

public delegate void EventHandler (object sender, EventArgs e)

il faut un émetteur (de type d'Objet) et les arguments d'événement. L'expéditeur est null si il s'agit de méthodes statiques.

Vous pouvez aussi utiliser l' EventHAndler au lieu cet exemple que l'utilisation EventHandler<ArgsSpecial>

reportez-vous ici pour la documentation sur EventHandler

111voto

Jorge Córdoba Points 18919

En plus de la syntaxe et de propriétés fonctionnelles, il y a aussi un semantical différence.

Les délégués sont, sur le plan conceptuel, les modèles de fonction; c'est, ils expriment un contrat d'une fonction doit respecter pour être considéré comme du "type" de la délégué.

Les événements représentent ... eh bien, les événements. Ils sont destinés à alerter quelqu'un quand il se passe quelque chose et oui, ils adhèrent à un délégué définition, mais ils ne sont pas la même chose.

Même s'ils ont été exactement la même chose (du point de vue syntaxique et dans le code IL), il y aura toujours de la semantical différence. En général, je préfère avoir deux noms différents pour les deux concepts différents, même si ils sont utilisés de la même manière (ce qui ne signifie pas que je voudrais avoir le même code deux fois).

38voto

vibhu Points 581

C'est un vieux post, mais si quelqu'un trébuche sur elle, comme je l'ai fait ici est un autre bon lien pour consulter.. http://csharpindepth.com/Articles/Chapter2/Events.aspx

brièvement, le tenir à l'écart de l'article - les Événements sont l'encapsulation sur les délégués. Citation de l'article -

"Supposons que les événements n'existent pas en tant que concept en C#/.NET. Comment une autre classe de s'abonner à un événement?

Trois options:

  1. public delegatevariable

  2. délégué variable soutenu par une propriété

  3. délégué variable avec AddXXXHandler et RemoveXXXHandler méthodes

L'Option 1 est clairement horrible, pour toutes les raisons que nous avons en horreur les variables publiques.

L'Option 2 est mieux, mais permet aux abonnés de remplacer efficacement uns les autres, il serait trop facile d'écrire someInstance.MyEvent = gestionnaire d'événements, et qui remplacent toutes les gestionnaires d'événements plutôt que l'ajout d'un nouveau. En outre, vous devez toujours écrire l' les propriétés.

L'Option 3 est essentiellement ce que les événements de vous donner, mais avec une garantie de convention (généré par le compilateur et soutenu par des indicateurs dans le IL) et "libre" de la mise en œuvre si vous êtes heureux avec la sémantique le domaine-comme les événements de vous donner. S'abonner ou se désabonner à événements est encapsulé sans laisser l'arbitraire l'accès à la liste de gestionnaires d'événements, et les langues peuvent rendre les choses plus simples en fournissant syntaxe tant en terme de déclaration et d'abonnement."

5voto

Paul Hill Points 57

Vous pouvez également utiliser des événements dans les déclarations d'interface, pas pour les délégués.

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