Was ist das Geschäft mit den Delegierten?

7

Ich verstehe, dass Delegaten Methodenaufrufe kapseln. Aber ich habe Schwierigkeiten, ihre Bedürfnisse zu verstehen. Warum überhaupt Delegierte verwenden, für welche Situationen sind sie gedacht?

    
m.edmondson 20.09.2010, 11:27
quelle

8 Antworten

11

Ein Delegat ist im Grunde ein Methodenzeiger. Ein Delegat lässt uns eine Referenzvariable erstellen, aber statt auf eine Instanz einer Klasse zu verweisen, verweist sie auf eine Methode innerhalb der Klasse. Es verweist auf jede Methode, die einen Rückgabetyp und dieselben Parameter wie von diesem Delegat angegeben hat. Es ist ein sehr nützlicher Aspekt der Veranstaltung. Zum gründlichen Lesen empfehle ich Ihnen, das Thema in Head First C # (von Andrew Stellman und Jennifer Greene) zu lesen. Es erklärt schön das Thema des Delegates sowie die meisten Konzepte in .NET.

    
sumit_programmer 20.09.2010, 11:59
quelle
8

Nun, einige häufige Anwendungen:

  • Event-Handler (sehr häufig im UI-Code - "Wenn der Button angeklickt wird, möchte ich, dass dieser Code ausgeführt wird")
  • Rückrufe von asynchronen Anrufen
  • Bereitstellung eines Threads (oder des Threadpools) mit einer neuen auszuführenden Aufgabe
  • Angabe von LINQ-Projektionen / Bedingungen usw.

Denken Sie nicht daran, dass Methodenaufrufe eingekapselt werden. Stellen Sie sich vor, dass sie ein beliebiges Bit Verhalten / Logik mit einer bestimmten Signatur kapseln. Der Teil "Methode" ist irrelevant.

Eine andere Art, einen Delegattyp zu denken, ist eine einzige Methodenschnittstelle. Ein gutes Beispiel hierfür ist die IComparer<T> Schnittstelle und ihr Dual, die Comparison<T> Delegattyp. Sie repräsentieren die gleiche Grundidee; Manchmal ist es einfacher, dies als Delegierter auszudrücken, und manchmal erleichtert eine Schnittstelle das Leben. (Sie können natürlich einfach Code schreiben, um zwischen den beiden zu konvertieren.)

    
Jon Skeet 20.09.2010 11:32
quelle
5

Sie sind sehr weit ausgelegt, wenn Sie Code haben, von dem Sie wissen, dass er anderen Code aufrufen muss - aber Sie wissen zur Kompilierzeit nicht, was dieser andere Code sein könnte.

Stellen Sie sich zum Beispiel das Windows Forms Button.Click-Ereignis vor, das einen Delegaten verwendet. Die Windows Forms-Programmierer wissen, dass etwas passieren soll, wenn diese Schaltfläche gedrückt wird, aber sie haben keine Möglichkeit, genau zu wissen, was Sie tun wollen ... es könnte alles Mögliche sein!

Sie erstellen also eine Methode und weisen sie einem Delegaten zu und legen sie für dieses Ereignis fest, und schon sind Sie da. Das ist die grundlegende Argumentation für die Delegierten, obwohl es viele andere gute Verwendungen für sie gibt, die verwandt sind.

    
Andrew Barber 20.09.2010 11:33
quelle
4

Delegierte werden oft für Events verwendet. Laut MSDN sind Delegaten in .NET für Folgendes konzipiert:

  
  • Ein Evening Design Pattern wird verwendet.
  •   
  • Es ist wünschenswert, eine statische Methode zu kapseln.
  •   
  • Der Aufrufer muss nicht auf andere Eigenschaften, Methoden oder Schnittstellen zugreifen   das Objekt, das die Methode implementiert.
  •   
  • Einfache Zusammensetzung ist erwünscht.
  •   
  • Eine Klasse benötigt möglicherweise mehr als eine Implementierung der Methodenimplementierung der Methode
  •   

Noch eine gute Erklärung von MSDN,

  

Ein gutes Beispiel für die Verwendung eines   Single-Methode-Schnittstelle anstelle von a   Delegat ist IComparable oder   %Code%. IComparable deklariert die   CompareTo-Methode, die ein   Ganzzahl, die a weniger als, gleich   zu oder größer als Beziehung   zwischen zwei Objekten desselben Typs.   IComparable kann als Basis verwendet werden   eines Sortieralgorithmus und während der Verwendung von a   Delegate Vergleichsmethode als die   Grundlage eines Sortieralgorithmus wäre   gültig, es ist nicht ideal. Weil das   Vergleichbarkeit gehört zum   Klasse und der Vergleichsalgorithmus   ändert sich zur Laufzeit nicht, a   Single-Methode-Schnittstelle ist ideal. Single-Methode-Schnittstelle ist ideal.

Seit .NET 2.0 wurde es auch für anonyme Funktionen .

Wikipedia hat eine schöne Erklärung zum Delegationsmuster,

  

In der Softwareentwicklung ist das Delegierungsmuster ein Entwurfsmuster in der objektorientierten Programmierung, bei dem ein Objekt diese Aufgabe an ein zugehöriges Hilfsobjekt delegiert, anstatt eine der angegebenen Aufgaben auszuführen. Es übergibt sozusagen den Bock (technisch eine Inversion of Responsibility). Das Hilfsobjekt heißt Delegat. Das Delegationsmuster ist eines der grundlegenden Abstraktionsmuster, die anderen Softwaremustern wie Komposition (auch als Aggregation bezeichnet), Mixins und Aspekten zugrunde liegen.

    
Filip Ekberg 20.09.2010 11:32
quelle
1

Übervereinfacht: Ich würde sagen, dass ein Delegat ein Platzhalter für eine Funktion ist, bis zu dem Zeitpunkt, an dem dem Delegierten eine echte Funktion zugewiesen wird. Der Aufruf von nicht zugewiesenen Delegaten löst eine Ausnahme aus.

Verwirrung tritt auf, weil zwischen der Definition, Deklaration, Instanziierung und dem Aufruf von Delegierten oft ein kleiner Unterschied besteht.

Definition:
Fügen Sie dies in einen Namensraum ein, wie Sie es bei jeder Klassendefinition tun würden.

%Vor%

Dies ist vergleichbar mit einer Klassendefinition, in der Sie jetzt Variablen dieses Delegaten deklarieren können.

Erklärung:
Setzen Sie das ist eine der Funktionsroutinen wie Sie jede Variable deklarieren würden.

%Vor%

Instantiierung und Zuweisung:
Normalerweise machst du das zusammen mit der Deklaration.

%Vor%

Das "neue DoSomething (..)" ist die Instanziierung. Die doSth = ... ist die Aufgabe.

Beachten Sie, dass Sie bereits eine Funktion namens "MyDoSomething" definiert haben, die eine Zeichenfolge akzeptiert und ein Bool zurückgibt.

Dann können Sie die Funktion aufrufen.

Aufruf:

%Vor%

Ereignisse:
Sie können sehen, wo Ereignisse eintreten:

Da ein Mitglied einer Klasse normalerweise eine Deklaration ist, die auf einer Definition basiert.
Wie

%Vor%

Ein Ereignis ist eine Deklaration, die auf einem Delegaten basiert:

%Vor%

Der Unterschied zum vorherigen Beispiel ist, dass Ereignisse "besonders" sind:

  1. Sie können nicht zugewiesene Ereignisse aufrufen, ohne eine Ausnahme auszulösen.
  2. Sie können einem Ereignis mehrere Funktionen zuweisen. Sie werden dann alle nacheinander aufgerufen. Wenn einer dieser Aufrufe eine Ausnahme auslöst, kann der Rest nicht abgespielt werden.

Sie sind wirklich syntaktischer Zucker für Arrays von Delegierten.

Der Punkt ist natürlich, dass etwas / jemand anderes das Zuweisen für Sie übernimmt.

    
Vincent Vancalbergh 22.11.2012 16:59
quelle
0

Delegaten ermöglichen Ihnen, einen Verweis auf eine Methode zu übergeben. Ein bekanntes Beispiel ist das Übergeben einer Vergleichsmethode an eine Sortierfunktion.

    
Brian Rasmussen 20.09.2010 11:32
quelle
0

Wenn Sie zur Laufzeit entscheiden müssen, welche Methode Sie aufrufen möchten, verwenden Sie einen Delegaten. Der Delegat wird dann zur Laufzeit auf eine Aktion / ein Ereignis reagieren und die entsprechende Methode aufrufen. Es ist so, als würde man einen "Delegierten" zu einer Hochzeit schicken, an der man selbst nicht teilnehmen möchte: -)

Die C-Leute werden dies als Funktionszeiger erkennen, aber lassen Sie sich hier nicht in die Terminologie verstricken. Alle Delegaten tun dies (und es ist tatsächlich ein Typ), stellt die Signatur der Methode bereit, die später aufgerufen wird, um die entsprechende Logik zu implementieren.

Das Buch "Illustrated C #" von Dan Solis bietet den einfachsten Einstieg für das Erlernen dieses Konzepts, auf das ich gestoßen bin:

Ссылка

    
IrishChieftain 20.09.2010 13:01
quelle
0

Ein Delegat ist in der Regel eine Kombination aus einer Objektreferenz und einem Zeiger auf eine der Klassenmethoden des Objekts (Delegaten können für statische Methoden erstellt werden; in diesem Fall gibt es keine Objektreferenz). Delegierte können ohne Berücksichtigung des Typs des eingeschlossenen Objekts aufgerufen werden, da der eingeschlossene Methodenzeiger für das enthaltene Objekt garantiert gültig ist.

Um etwas über die Nützlichkeit der Delegierten zu verstehen, sollten Sie sich an die Sprache C und die printf "Familie" der Funktionen in C erinnern. Angenommen, Sie wollten eine universelle Version von "printf", die nicht nur verwendet werden kann B. printf, fprintf, sprintf usw., könnte aber seine Ausgabe an einen seriellen Port, eine Textbox, einen TCP-Port, eine Cookie-Frosting-Maschine oder was auch immer senden, ohne einen Puffer vorab reservieren zu müssen. Natürlich müsste eine solche Funktion einen Funktionszeiger für die Zeichenausgaberoutine akzeptieren, aber das wäre im Allgemeinen nicht ausreichend.

Eine typische Implementierung (leider nicht standardisiert) wird eine allgemeine gp_printf-Routine haben, die (zusätzlich zu der Formatzeichenfolge und Ausgabeparametern) einen void-Zeiger und einen Zeiger auf eine Funktion akzeptiert, die ein Zeichen und einen void-Zeiger akzeptiert . Die gp_printf-Routine verwendet den übergebenen void-Zeiger nicht für irgendeinen Zweck selbst, sondern übergibt ihn an die Zeichenausgabefunktion. Diese Funktion kann dann den Zeiger auf eine FILE * (wenn gp_printf von fprintf aufgerufen wird) oder ein Zeichen ** (wenn es von sprintf aufgerufen wird) oder ein SERIAL_PORT * (wenn es von serial_printf aufgerufen wird) oder was auch immer ausgeben .

Beachten Sie, dass, da jede Art von Information über das void * weitergegeben werden könnte, es keine Beschränkung gg_printf gäbe. Es würde jedoch eine Gefahr geben: Wenn die in der Lücke * übermittelte Information nicht das ist, was die Funktion erwartet, würde Undefiniertes Verhalten (d. H. Potentiell sehr schlimme Dinge) wahrscheinlich resultieren. Es wäre die Verantwortung des Anrufers sicherzustellen, dass der Funktionszeiger und void * richtig gepaart sind; nichts im System würde vor falscher Verwendung schützen.

In .net würde ein Delegat die kombinierte Funktionalität des Funktionszeigers und void * oben bereitstellen, mit dem zusätzlichen Vorteil, dass der Konstruktor des Delegaten sicherstellen würde, dass die Daten vom richtigen Typ für die Funktion waren. Eine praktische Funktion.

    
supercat 24.09.2010 16:15
quelle

Tags und Links