Quelle est la différence entre délégué et événement en C #?

Duplication possible:
Quelle est la différence entre un délégué et des événements?

Cette question que j’ai eu lors d’une interview et je ne sais toujours pas quelle devrait être la réponse.
J’apprécierais n’importe quelles pensées!

J’ai un article à peu près exactement

En bref, vous pouvez considérer un événement comme un peu comme une propriété, mais au lieu d’avoir des opérations get / set, il a été ajouté / supprimé. La valeur ajoutée / supprimée est toujours une référence de délégué.

Les delegates eux-mêmes soutiennent les opérations de:

  • Combiner (chaîner plusieurs instances de délégué ensemble)
  • Supprimer (les diviser à nouveau)
  • Invoquer (synchrone ou asynchrone)
  • Diverses choses à voir avec la recherche de la cible, la liste d’invocation, etc.

Notez que les delegates eux-mêmes sont immuables, donc les opérations combine / remove renvoient une nouvelle instance de délégué plutôt que de modifier celles existantes.

Les autres réponses sont jusqu’ici assez bonnes. Voici une autre façon d’y penser.

Quelle est la différence sémantique entre une propriété et un champ ? Je ne veux pas dire quelles sont les différences techniques, comme une propriété est en fait une paire de méthodes, bla bla bla. Je veux dire, en ce qui concerne la compréhension du sens d’un programme, quelle est la différence?

Une propriété est généralement un membre public d’une classe et représente une propriété de la chose en cours de modélisation. C’est-à-dire que vous voulez créer un modèle de journal afin de créer un journal de classe et de lui donner un éditeur de propriété. L’éditeur est une propriété des journaux, donc Publisher est une propriété de la classe Newspaper.

Un champ est généralement un détail d’implémentation d’une classe. La propriété Publisher est peut-être implémentée en tant que champ. Mais les journaux n’ont pas de “champs”, donc vous n’exposez pas le champ éditeur en tant que membre public de la classe Newspaper; vous l’utilisez comme détail d’implémentation privé de la propriété Publisher.

Les événements et les delegates sont quelque peu analogues. Un événement est quelque chose dans le modèle . Un bouton est une chose qui peut vous informer quand il est cliqué, donc la classe Button a un événement “Click”. Le délégué qui fait l’information est le détail de l’implémentation de l’événement.

Fondamentalement, un délégué est juste un wrapper autour de ce qui serait un pointeur de fonction dans C (ou une liste de pointeurs de fonction).

Un événement est une abstraction de niveau encore plus élevé qui englobe le concept d’un délégué avec des méthodes pour s’abonner et se désabonner d’une méthode à ces delegates.

Un événement est une «propriété» qui expose une méthode d’ add et de remove (appelée via += et -= dans le code) pour append / supprimer des abonnés à une liste de delegates.

Un délégué est similaire à un pointeur de fonction en C / C ++. Il contient une référence à une méthode et à une instance d’object (si la méthode n’est pas statique). Les delegates sont généralement multicast, c’est-à-dire qu’ils contiennent des références à plusieurs paires object / méthode.

Un événement est un mécanisme de notification, basé sur les delegates. La seule chose qu’il expose publiquement est une paire de méthodes (add / remove) pour s’abonner ou se désinscrire de la notification. Un type de délégué est utilisé pour définir la signature des méthodes de gestionnaire, et la liste des abonnés est (généralement) stockée en interne en tant que délégué.

J’admets volontiers que cette réponse ne compare pas la différence entre les delegates et les événements. Cependant, je pense qu’avec les réponses que d’autres ont données pour les événements avec une explication un peu plus détaillée sur les delegates, vous verrez la différence entre les deux. Plus spécifiquement, une fois que vous aurez une compréhension plus claire des delegates, je pense que vous gagnerez une différence conceptuelle entre les delegates et les événements.

Ce qui m’a aidé à comprendre ce qu’est un délégué, c’est de ne les considérer que comme un conteneur pour une méthode unique.

Pour conceptualiser la façon dont un délégué est un “conteneur” d’une méthode, consultez cet exemple qui utilise un délégué pour appeler trois méthodes différentes. Notez que même si la même instance de délégué est utilisée pour appeler trois méthodes différentes, l’instance du délégué contiendra uniquement (ou cible) une méthode à un moment donné.

 class Program { delegate void MyDelegate(); static void Main() { //Notice how we use the same delegate instance //to target different methods of the same signature MyDelegate myDelegate = new MyDelegate(MethodA); myDelegate(); //Invoke the method myDelegate = MethodB; myDelegate(); myDelegate = MyClass.MethodZ; myDelegate(); Console.ReadLine(); } static void MethodA() { Console.WriteLine("Method 'A' is doing work."); } static void MethodB() { Console.WriteLine("Method 'B' is doing work."); } class MyClass { public static void MethodZ() { Console.WriteLine("Method 'Z' of MyClass is doing work"); } } } 

Vous remarquerez que le délégué dans l’exemple peut contenir / target n’importe quelle méthode qui a la même signature que le délégué (renvoie void et prend zéro paramètre dans notre exemple). Si vous vous arrêtez ici pour digérer ce principe, vous commencez bien à comprendre les delegates.

Cela étant dit, ce qui m’a déconcerté au sujet des delegates, c’est quand je mettrais explicitement en œuvre des delegates dans mon code. L’exemple de programme ci-dessus utilise explicitement un délégué, mais il n’y a aucune raison pratique de le faire puisque la méthode Main () aurait tout aussi bien pu appeler directement les méthodes cibles, c’est-à-dire que nous aurions pu faire …

 static void Main() { MethodA(); MethodB(); MyClass.MethodZ(); Console.ReadLine(); } 

Alors, quel est l’exemple de l’implémentation d’un délégué explicitement? Jon Skeet m’a aidé à répondre à cette question quand il a dit

… vous pouvez penser à un type de délégué comme un peu comme une interface avec une seule méthode.

Sachant qu’un délégué est un conteneur pour une méthode et, maintenant, considérant qu’un délégué est comme une interface avec une méthode unique, considérez ceci:

Disons que nous avons un programme qui démarrera les moteurs de différents types de véhicules – voiture, moto et avion.

Notre programme comprendra des classes de véhicules – une classe pour chaque type de véhicule. Chaque classe de véhicule est responsable du démarrage de son propre moteur. De plus, à l’instar de l’implémentation d’une interface, chaque classe s’assurera que sa méthode qui démarre son propre moteur aura une signature spécifiée comme toutes les autres classes (et la principale).

Nous avons donc quelque chose comme ça:

 class VehicleProgram { //All vehicle classes implement their own engine starter method that has this signature delegate void StartEngine(); static void Main() { //The Main doesn't know the details of starting an engine. //It delegates the responsibility to the concrete vehicle class foreach (StartEngine starter in GetVehicleStarters()) { starter(); //Invoke the method } Console.ReadLine(); } static List GetVehicleStarters() { //Create a list of delegates that target the engine starter methods List starters = new List(); starters.Add(Car.StartCar); starters.Add(Motorcycle.StartMotorcycle); starters.Add(Airplane.StartAirplane); return (starters); } class Car { public static void StartCar() { Console.WriteLine("The car is starting."); } } class Motorcycle { public static void StartMotorcycle() { Console.WriteLine("The motorcycle is starting."); } } class Airplane { public static void StartAirplane() { Console.WriteLine("The airplane is starting."); } } } 

Comme les delegates détiennent des méthodes, nous avons pu implémenter une conception dans laquelle Main () obtient simplement une liste de delegates, puis appelle la méthode. Cette conception est très similaire à la façon dont nous implémentons les interfaces.

En savoir plus sur Quand utiliser les delegates au lieu des interfaces

Voici un très bon article à ce sujet.

http://www.akadia.com/services/dotnet_delegates_and_events.html

Fondamentalement, les événements fournissent un paradigme de souscription de publication étroitement couplé, tandis que les delegates prévoient une conception beaucoup moins souple.

Les événements sont plus simples et plus faciles à utiliser.

Les delegates ne sont rien d’autre qu’un pointeur de fonction, dans lequel la fonction est appelée de manière asynchrone. Mais les événements ne sont que des notifications. Par exemple, cliquer sur un bouton est un événement, donc pour cela, vous devez vous abonner à l’événement click d’un bouton, etc.