Je sais que les événements sont toujours associés aux délégués. Mais, il me manque une utilisation fondamentale des événements et d'essayer de comprendre cela.
J'ai créé un programme d'événements simple, comme ci-dessous, et cela fonctionne parfaitement bien. P>
namespace CompleteRef3._0 { delegate void someEventDelegate(); class EventTester { someEventDelegate someEvent; public void doEvent() { if (someEvent != null) someEvent(); } } class Program { static void EventHandler1() { Console.WriteLine("Event handler 1 called.."); } static void EventHandler2() { Console.WriteLine("Event handler 2 called.."); } static void EventHandler3() { Console.WriteLine("Event handler 3 called.."); } static void Main(string[] args) { EventTester evt = new EventTester(); evt.someEvent += EventHandler1; evt.someEvent += EventHandler2; evt.someEvent += EventHandler3; evt.doEvent(); Console.ReadKey(); } } }
4 Réponses :
L'objectif principal des événements est de prévenir les abonnés d'interférer les uns avec les autres. Si vous n'utilisez pas d'événements, vous pouvez: p>
remplacer d'autres abonnés en réaffectant le délégué (au lieu d'utiliser l'opérateur + =), Effacer tous les abonnés (en définissant le délégué à NULL), Diffusé à d'autres abonnés en invoquant le délégué. P>
Source: C # en un mot p>
+1. Affectation SOMEVENT = nouveau SomeeventDelegate (EventHandler2) code> est le problème que vous avez avec une utilisation directe des délégotes. Un autre lien L'apprentissage C # 3.0: maître les principes fondamentaux de C # 3.0 - Délégués et événements - Ce chapitre particulier est avialble sur MSDN et participe à des détails sur ce sujet.
Bien sûr, vous pouvez utiliser des délégués parce que dans les coulisses, un événement est une construction qui enveloppe un délégué. P>
Mais la justification de l'utilisation d'événements au lieu de délégués est la même que pour utiliser des propriétés au lieu de champs - encapsulation de données em>. C'est une mauvaise pratique d'exposer directement les champs (quels qu'ils soient - des domaines ou des délégués primitifs) directement. P>
D'ailleurs, vous avez manqué un mot-clé code> code> avant votre champ de délégué pour la rendre possible dans le deuxième extrait. P>
Un autre "d'ailleurs" avec le deuxième extrait: Pour les délégués, vous devez utiliser Délégate.combine code> au lieu de "+ =". P>
oh ya .. ma erreur j'ai manqué le public code> mot-clé .. Merci de l'attraper pour moi. Je vais le modifier .. Bonne connaissance pour moi d'utiliser
Délégate.combine Code>. Je ne le connaissais pas avant! ... Votre réponse est bonne, exactement ce que je pensais - encapsulation de données i> b>.
Bonne réponse sauf pour la dernière ligne. Pourquoi ne devriez-nous pas utiliser + code> et
+ = code> et ainsi de suite avec des délégués? b> Ils ont été mis dans la langue pour rendre les choses jolies. Il est toujours important de comprendre la différence entre
+ = code> avec des événements (une syntaxe pour appeler l'accessor code> Ajouter code> Accessoir d'événement) et
+ = code> avec des variables (Ici
x + = y code> est un peu comme
x = x + y code> où
+ code> peut être une combinaison de délégation, une concaténation à la chaîne, une addition arithmétique de type , ou d'autres surcharges). Un problème avec
délégué.combine code> est que les types ne sont pas vérifiés à tout moment de compilation. Avec
+ code> Les types de compilération sont vérifiés.
Imaginez que vous avez 3 abonnés qui sont intéressés par votre SomeEvent. Imaginons plus avant qu'ils souhaitent recevoir des événements de la même instance Voici l'instance: p> eventester code>. Pour une brièveté, laissons les détails de la manière dont la même instance est exacte à tous les clients. Quand je dis clients em>, je veux dire n'importe quelle classe qui est un abonné à l'événement.
if (someEvent != null) someEvent();
Merci. Vous avez très bien expliqué l'utilisation de l'événement. :)
Je ne sais pas si d'autres utilisateurs ont eu cette question ou non, mais si tous les clients créent une instance séparée de la classe principale Eventestester. Ensuite, si le client 4 fait l'un des scénarios que vous avez mentionnés, les autres clients ne seront pas affectés? Ou si vous pouviez expliquer dans quel scénario tous les clients utiliseraient la même instance de la classe Eventester
@dihren correct, si une instance séparée, alors ce n'aurait pas d'importance. Voici un scénario: imaginez une application comme Visual Studio dans laquelle l'utilisateur change les paramètres et de nombreuses fenêtres doivent réagir et modifier en conséquence. Imaginez que l'un des programmeurs travaillant sur l'une des fenêtres a fait cela par erreur? Maintenant, je ne dis pas que VS est construit de cette façon, mais il y a un exemple. Il existe de nombreux scénarios, en particulier lorsque chaque composant est sa propre chose, mais ils s'abonnent tous à quelque chose dans une fenêtre unique.
@dihren dans les applications Big Enterprise, vous ne pouvez pas simplement aller dans un code> existant code> ou cliquez sur CODE> Handler et ajoutez du code, qui est froncé sur le fait que le code existant peut potentiellement introduire des bugs . Cela doit donc être fait de manière différente, peut-être utiliser le principe de fermeture ouvert. Lorsque vous avez un seul éditeur et plusieurs abonnés, vous rencontrez des dangers détaillés dans la réponse. Connaissant cela, vous pouvez proposer de nombreux scénarios vous-même maintenant :)
public class Program { public static void Main() { Number myNumber = new Number(100000); myNumber.PrintMoney(); myNumber.PrintNumber(); Console.ReadKey(); } } public class Number { private PrintHelper _printHelper; public Number(int val) { _value = val; _printHelper = new PrintHelper(); //subscribe to beforePrintEvent event _printHelper.beforePrintEvent += printHelper_beforePrintEvent; } //beforePrintevent handler void printHelper_beforePrintEvent(string message) { Console.WriteLine("BeforePrintEvent fires from {0}", message); } private int _value; public int Value { get { return _value; } set { _value = value; } } public void PrintMoney() { _printHelper.PrintMoney(_value); } public void PrintNumber() { _printHelper.PrintNumber(_value); } } public class PrintHelper { public delegate void BeforePrintDelegate(string message); public event BeforePrintDelegate beforePrintEvent; public PrintHelper() { } public void PrintNumber(int num) { if (beforePrintEvent != null) beforePrintEvent.Invoke("PrintNumber"); Console.WriteLine("Number: {0,-12:N0}", num); } public void PrintDecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent("PrintDecimal"); Console.WriteLine("Decimal: {0:G}", dec); } public void PrintMoney(int money) { if (beforePrintEvent != null) beforePrintEvent("PrintMoney"); Console.WriteLine("Money: {0:C}", money); } public void PrintTemperature(int num) { if (beforePrintEvent != null) beforePrintEvent("PrintTemerature"); Console.WriteLine("Temperature: {0,4:N1} F", num); } public void PrintHexadecimal(int dec) { if (beforePrintEvent != null) beforePrintEvent("PrintHexadecimal"); Console.WriteLine("Hexadecimal: {0:X}", dec); } }
Bien que ce code puisse résoudre la question, , y compris une explication de la manière et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre post et aboutit probablement à des votes supplémentaires. N'oubliez pas que vous répondez à la question pour les lecteurs à l'avenir, pas seulement la personne qui demande maintenant. Veuillez <-href="https://stackoverflow.com/posts/58464521/edit"> Modifier Votre réponse pour ajouter des explications et donner une indication de quelles limitations et hypothèses s'appliquent.
En bref, exposant les pannes de délégué publics encapsulation b>.