27 votes

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

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

J'ai posé cette question lors d'un entretien et je ne sais toujours pas quelle devrait être la réponse.
J'apprécierais toutes les pensées!

47voto

Jon Skeet Points 692016

J'ai un article sur à peu près exactement

En bref, vous pouvez penser à un événement comme un peu comme une propriété, mais au lieu d'obtenir/définir les opérations, il a ajouter/supprimer. La valeur ajoutée/supprimée est toujours un délégué de référence.

Les délégués eux-mêmes les opérations de soutien de:

  • Combiner (chaîne de multiples délégué ensemble d'instances)
  • Supprimer (les séparer de nouveau)
  • Invoke (synchrone ou asynchrone)
  • Diverses choses à faire avec la recherche de la cible, l'invocation de liste, etc

Noter que les délégués eux-mêmes sont immuables, afin de combiner les opérations de suppression renvoyer une nouvelle instance de délégué plutôt que de modifier ceux existants.

37voto

Eric Lippert Points 300275

Les autres réponses sont tous très bon. Voici une autre façon de penser.

Quelle est la sémantique différence entre une propriété et d'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, autant que la compréhension de la signification d'un programme, quelle est la différence?

Une propriété est généralement un public membre d'une classe, et il représente une propriété de la chose en cours de modélisation. Qui est, vous voulez faire un modèle d'un journal de sorte que vous faites un Journal de classe, et vous donner une propriété de l'Éditeur. L'éditeur est une propriété de journaux, de sorte que l'Éditeur est une propriété du Journal de classe.

Un champ est généralement un détail de l'implémentation d'une classe. Peut-être l'Éditeur de la propriété est effectivement mis en œuvre comme un champ. Mais les journaux n'ont pas de "champs", afin de ne pas exposer l'éditeur de terrain en tant que membre du public du Journal de classe; vous l'utiliser comme un privé détail de l'implémentation de l'Éditeur de la propriété.

Les événements et les délégués sont un peu analogue. Un événement est quelque chose dans le modèle. Un bouton est une chose qui peut vous informer lorsqu'il est cliqué, alors le Bouton de classe a un événement "Click". Le délégué qui en fait l'information est la mise en œuvre détail de l'événement.

14voto

Konrad Rudolph Points 231505

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

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

Un événement est une "propriété" qui expose une add et remove méthode (appelé à l'aide d' += et -= dans le code) à ajouter/supprimer des abonnés à un délégué de liste.

5voto

Jed Points 3592

J'admets que cette réponse n'est pas de comparer la différence entre les délégués et les événements. Cependant, je pense que les réponses que d'autres ont donné pour les Événements avec un peu plus d'explication détaillée sur les délégués, vous verrez la différence entre les deux. Plus précisément, une fois que vous avez une meilleure compréhension de délégués, je pense que vous aurez une différence conceptuelle entre les délégués et les événements.

Ce qui m'a aidé dans la compréhension de ce qu'est un délégué est, est en pensant à eux comme rien de plus qu'un conteneur pour une seule et unique méthode.

À conceptualiser comment un délégué est un "container" d'une méthode, d'examiner cet exemple qui rend l'utilisation d'un délégué à invoquer trois différentes méthodes de Noter que, bien que la même instance de délégué est utilisé pour invoquer les trois méthodes différentes, l'instance de délégué ne contiennent (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é de l'exemple peut contenir/cible toute méthode qui a la même signature que le délégué (void et prend zéro des paramètres dans notre exemple). Si vous faites une pause ici et de digérer ce principe, vous êtes hors d'un bon départ dans la compréhension des délégués.

Avec cela étant dit, ce qui me confond sur les délégués, c'est quand je n'aurais jamais explicitement de mettre en œuvre les délégués dans mon code. L'exemple de programme ci-dessus explicitement fait appel à un délégué, mais il n'y a aucune raison pratique à le faire depuis la méthode main() pourrait tout aussi bien avoir appelé la cible des méthodes directement - c'est à dire que nous pourrions viens de le faire...

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

    Console.ReadLine();
}

Alors, quel est un exemple de cas où nous voudrions mettre en œuvre un délégué explicitement? Jon Skeet m'a aidé à répondre à cette question quand il a dit

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

Sachant qu'un délégué est un conteneur pour une méthode et, maintenant, en considérant qu'un délégué, c'est comme une Interface avec une seule méthode, considérez ceci:

Dire que nous avons un programme qui va démarrer les moteurs des différents types de véhicules (Voiture, Moto et Avion.

Notre programme sera composé des classes de véhicules - une classe pour chaque type de véhicule. Chaque catégorie de véhicule est chargé du lancement de son propre moteur. En outre, similaire à la mise en œuvre d'une Interface, chaque classe assurez-vous que sa méthode qui lance son propre moteur, aura spécifié signature que toutes les autres classes (et le Principal) convenir.

Nous avons donc quelque chose comme ceci:

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<StartEngine> GetVehicleStarters()
    {
        //Create a list of delegates that target the engine starter methods
        List<StartEngine> starters = new List<StartEngine>();

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

Depuis délégués tenir méthodes, nous avons été en mesure de mettre en œuvre une conception où le main() obtient tout simplement une liste des délégués qui appelle ensuite la méthode. Cette conception est très similaire à la façon dont nous mettons en œuvre des Interfaces.

Lire plus sur Quand Utiliser les Délégués à la Place d'Interfaces

2voto

Thomas Levesque Points 141081

Un délégué est semblable à un pointeur de fonction en C/C++. Il contient une référence à une méthode et à une instance d'objet (si la méthode non-statique). Les délégués sont généralement de multidiffusion, c'est à dire qu'ils contiennent des références à plusieurs d'objet, de méthode, de paires.

Un événement est un mécanisme de notification, basé sur les délégués. La seule chose qu'il expose en public est une paire de méthodes (ajouter/supprimer) pour vous abonner ou vous désabonner à partir de la notification. Un délégué de type est utilisé pour définir la signature des méthodes de gestionnaire, et la liste des abonnés sont (généralement) enregistrées dans la mémoire interne en tant que délégué.

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