Délégués, pourquoi?

Dupliqués possibles:
Quand utiliseriez-vous des delegates en C #?
Le but des delegates

J’ai vu beaucoup de questions concernant l’utilisation des delegates. Je ne suis toujours pas sûr où et pourquoi utiliseriez-vous des delegates au lieu d’appeler directement la méthode.

J’ai entendu cette phrase à plusieurs resockets: “L’object délégué peut ensuite être transmis au code qui peut appeler la méthode référencée, sans avoir à connaître au moment de la compilation quelle méthode sera invoquée.”

Je ne comprends pas comment cette déclaration est correcte.

J’ai écrit les exemples suivants. Disons que vous avez 3 méthodes avec les mêmes parameters:

public int add(int x, int y) { int total; return total = x + y; } public int multiply(int x, int y) { int total; return total = x * y; } public int subtract(int x, int y) { int total; return total = x - y; } 

Maintenant, je déclare un délégué:

 public delegate int Operations(int x, int y); 

Maintenant, je peux aller plus loin en déclarant un gestionnaire d’utiliser ce délégué (ou votre délégué directement)

Appelez le délégué:

 MyClass f = new MyClass(); Operations p = new Operations(f.multiply); p.Invoke(5, 5); 

ou appelez avec le gestionnaire

 f.OperationsHandler = f.multiply; //just displaying result to text as an example textBoxDelegate.Text = f.OperationsHandler.Invoke(5, 5).ToSsortingng(); 

Dans ces deux cas, je vois ma méthode de multiplication spécifiée. Pourquoi les gens utilisent-ils l’expression “modifier la fonctionnalité à l’exécution” ou celle ci-dessus?

Pourquoi les delegates sont-ils utilisés si chaque fois que je déclare un délégué, il doit utiliser une méthode pour la signaler? et s’il a besoin d’une méthode pour pointer, pourquoi ne pas appeler cette méthode directement? Il me semble que je dois écrire plus de code pour utiliser les delegates que pour utiliser directement les fonctions.

Quelqu’un peut-il s’il vous plaît me donner une situation réelle du monde? Je suis totalement confus.

Changer de fonctionnalité à l’exécution n’est pas ce que les delegates accomplissent.

Fondamentalement, les delegates vous permettent d’économiser de la saisie.

Par exemple:

 class Person { public ssortingng Name { get; } public int Age { get; } public double Height { get; } public double Weight { get; } } IEnumerable people = GetPeople(); var orderedByName = people.OrderBy(p => p.Name); var orderedByAge = people.OrderBy(p => p.Age); var orderedByHeight = people.OrderBy(p => p.Height); var orderedByWeight = people.OrderBy(p => p.Weight); 

Dans le code ci-dessus, les p => p.Name , p => p.Age , etc. sont toutes des expressions lambda évaluées en delegates Func (où T est respectivement ssortingng , int , double et double . ).

Considérons maintenant comment nous aurions pu réaliser ce qui précède sans les delegates. Au lieu d’avoir la méthode OrderBy prenant un paramètre délégué, il faudrait abandonner la généricité et définir ces méthodes:

 public static IEnumerable OrderByName(this IEnumerable people); public static IEnumerable OrderByAge(this IEnumerable people); public static IEnumerable OrderByHeight(this IEnumerable people); public static IEnumerable OrderByWeight(this IEnumerable people); 

Cela serait totalement nul . Je veux dire, premièrement, le code est devenu infiniment moins réutilisable, car il ne s’applique qu’aux collections du type Person . En outre, nous devons copier et coller le même code quatre fois, en ne modifiant que 1 ou 2 lignes dans chaque copie (lorsque la propriété correspondante de Person est référencée, sinon tout se ressemblerait)! Cela deviendrait rapidement un désordre immuable.

Les delegates vous permettent donc de rendre votre code plus réutilisable et plus facile à entretenir en éliminant certains comportements du code qui peuvent être activés ou désactivés.

Délégués .NET: AC # Bedtime Story

Les delegates sont extrêmement utiles, surtout après l’introduction de linq et des fermetures.

Un bon exemple est la fonction «Where», une des méthodes linq standard. «Where» prend une liste et un filtre et renvoie une liste des éléments correspondant au filtre. (L’argument filter est un délégué qui prend un T et retourne un booléen.)

Comme il utilise un délégué pour spécifier le filtre, la fonction Where est extrêmement flexible. Vous n’avez pas besoin de fonctions Where différentes pour filtrer les nombres impairs et les nombres premiers, par exemple. La syntaxe d’appel est également très concise, ce qui ne serait pas le cas si vous utilisiez une interface ou une classe abstraite.

Plus concrètement, prendre un délégué signifie que vous pouvez écrire ceci:

 var result = list.Where(x => x != null); ... 

au lieu de cela:

 var result = new List(); foreach (var e in list) if (e != null) result.add(e) ... 

Pourquoi les delegates sont-ils utilisés si chaque fois que je déclare un délégué, il doit utiliser une méthode pour le signaler? et s’il a besoin d’une méthode pour pointer, pourquoi ne pas appeler cette méthode directement?

Comme les interfaces, les delegates vous permettent de découpler et de généraliser votre code. Vous utilisez généralement des delegates lorsque vous ne savez pas à l’avance quelles méthodes vous souhaitez exécuter – lorsque vous savez seulement que vous voulez exécuter quelque chose correspondant à une certaine signature.

Par exemple, considérons une classe de temporisation qui exécutera une méthode à intervalles réguliers:

 public delegate void SimpleAction(); public class Timer { public Timer(int secondsBetweenActions, SimpleAction simpleAction) {} } 

Vous pouvez twigr n’importe quoi dans cette timer, de sorte que vous pouvez l’utiliser dans tout autre projet ou application sans essayer de prédire comment vous allez l’utiliser et sans limiter son utilisation à une poignée de scénarios auxquels vous songez actuellement .

Laissez-moi vous donner un exemple. Si votre classe expose un event , il peut être affecté à un certain nombre de delegates à l’exécution, qui sera appelé pour signaler que quelque chose s’est produit. Quand vous avez écrit le cours, vous n’aviez aucune idée de ce que les delegates finiraient par courir. Au lieu de cela, ceci est déterminé par celui qui utilise votre classe.

Pour donner un exemple concret, une utilisation particulièrement récente d’un délégué a été SendAsync() sur System.Net.Mail.SmtpClient . J’ai une application qui envoie des tonnes et des tonnes de courriels et il y a eu un problème de performance notable en attendant que le serveur Exchange accepte le message. Cependant, il était nécessaire de consigner le résultat de l’interaction avec ce serveur.

J’ai donc écrit une méthode de délégué pour gérer cette journalisation et l’ SendAsync() transmise à SendAsync() (nous SendAsync() auparavant Send() ) lors de l’envoi de chaque courrier électronique. De cette manière, il peut rappeler le délégué pour consigner le résultat et les threads de l’application n’attendent pas la fin de l’interaction avant de continuer.

La même chose peut être vraie pour tout E / S externe sur lequel vous souhaitez que l’application continue sans attendre la fin de l’interaction. Les classes de proxy pour les services Web, etc. en profitent.

Un exemple où un delegate est nécessaire est lorsque vous devez modifier un contrôle dans le thread d’interface utilisateur et que vous travaillez dans un thread différent. Par exemple,

 public delegate void UpdateTextBox(ssortingng data); private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { ... Invoke(new UpdateTextBox(textBoxData), data); ... } private void textBoxData(ssortingng data) { textBox1.Text += data; } 

Dans votre exemple, une fois que vous avez atsortingbué un délégué à une variable, vous pouvez le transmettre comme toute autre variable. Vous pouvez créer une méthode acceptant un délégué en tant que paramètre et appeler le délégué sans avoir à savoir où la méthode est réellement déclarée.

 private int DoSomeOperation( Operations operation ) { return operation.Invoke(5,5); } ... MyClass f = new MyClass(); Operations p = new Operations(f.multiply); int result = DoSomeOperation( p ); 

Les delegates font des méthodes dans des choses que vous pouvez faire circuler de la même manière qu’un int. Vous pourriez dire que les variables ne vous apportent rien d’autre car

 int i = 5; Console.Write( i + 10 ); 

vous voyez que la valeur 5 est spécifiée, alors vous pourriez aussi bien dire Console.Write( 5 + 10 ) . C’est vrai dans ce cas, mais il manque les avantages de pouvoir dire

 DateTime nextWeek = DateTime.Now.AddDays(7); 

au lieu de définir une méthode DateTime.AddSevenDays() spécifique, une méthode AddSixDays , etc.

Vous pouvez utiliser des delegates pour implémenter des abonnements et des eventHandlers. Vous pouvez également (de manière terrible) les utiliser pour contourner les dépendances circulaires.

Ou si vous avez un moteur de calcul et qu’il existe de nombreux calculs possibles, vous pouvez utiliser un délégué de parameters au lieu de nombreux appels de fonctions différents pour votre moteur.

À l’aide de votre exemple d’ Operations , imaginez une calculasortingce comportant plusieurs boutons. Vous pouvez créer une classe pour votre bouton comme ceci

 class CalcButton extends Button { Operations myOp; public CalcButton(Operations op) { this.myOp=op; } public void OnClick(Event e) { setA( this.myOp(getA(), getB()) ); // perform the operation } } 

et puis, lorsque vous créez des boutons, vous pouvez créer chacun avec une opération différente

 CalcButton addButton = new CalcButton(new Operations(f.multiply)); 

C’est mieux pour plusieurs raisons. Vous ne répliquez pas le code dans les boutons, ils sont génériques. Vous pourriez avoir plusieurs boutons qui ont tous la même opération, par exemple sur différents panneaux ou menus. Vous pouvez modifier l’opération associée à un bouton à la volée.

Les delegates sont utilisés pour résoudre un problème d’access. Quand vous voulez avoir un object foo qui doit appeler la méthode frob de la barre d’object, mais qui n’a pas access à la méthode frob.

L’object goo a access à la fois au foo et à la barre pour qu’il puisse le relier à l’aide de delegates. Typiquement, la barre et le goo sont souvent le même object.

Par exemple, une classe Button n’a généralement aucun access à la classe définit une méthode Button_click.

Donc, maintenant que nous avons cela, nous pouvons l’utiliser pour beaucoup d’autres choses que des événements. Les modèles Asynch et Linq en sont deux exemples.

Il semble que beaucoup de réponses concernent des delegates en ligne, ce qui, à mon avis, est plus facile à comprendre que ce que j’appellerai des “delegates classiques”.

Vous trouverez ci-dessous un exemple de la manière dont les delegates permettent à une classe consommasortingce de modifier ou d’augmenter son comportement (en ajoutant efficacement des “hooks” pour qu’un consommateur puisse faire des choses avant ou après une action critique et / ou empêcher ce comportement). Notez que toute la logique de prise de décision est fournie en dehors de la classe SsortingngSaver . Maintenant, considérez qu’il peut y avoir 4 consommateurs différents de cette classe – chacun d’entre eux peut implémenter sa propre logique de Verification et de Notification , ou aucune, le cas échéant.

 internal class SsortingngSaver { public void Save() { if(BeforeSave != null) { var shouldProceed = BeforeSave(thingsToSave); if(!shouldProceed) return; } BeforeSave(thingsToSave); // do the save if (AfterSave != null) AfterSave(); } IList thingsToSave; public void Add(ssortingng thing) { thingsToSave.Add(thing); } public Verification BeforeSave; public Notification AfterSave; } public delegate bool Verification(IEnumerable thingsBeingSaved); public delegate void Notification(); public class SomeUtility { public void SaveSomeSsortingngs(params ssortingng[] ssortingngs) { var saver = new SsortingngSaver { BeforeSave = ValidateSsortingngs, AfterSave = ReportSuccess }; foreach (var s in ssortingngs) saver.Add(s); saver.Save(); } bool ValidateSsortingngs(IEnumerable ssortingngs) { return !ssortingngs.Any(s => s.Contains("RESTRICTED")); } void ReportSuccess() { Console.WriteLine("Saved successfully"); } } 

Je suppose que le fait est que la méthode indiquée par le délégué n’est pas nécessairement dans la classe exposant le membre délégué.