2008-10-10 19 views
99

Wie verwenden Sie Delegierte in C#?Wann würden Sie Delegierte in C# verwenden?

+2

Meinst du Delegaten im .NET-Typ-System oder der C# -Delegaten-Syntax? Meinst du "wann benutzt du die Delegatensyntax anstelle der Lambda-Ausdruckssyntax?" Oder meinst du "Wann benutzt du Delegierte statt Klassen/Schnittstellen/virtuelle Methoden/etc."? – Niki

+0

[http://stackoverflow.com/questions/1137431/are-net-delegates-used-for-events](http://stackoverflow.com/questions/1137431/are-net-delegates-used-for-events) – Raghav

Antwort

97

Jetzt, wo wir Lambda-Ausdrücke und anonyme Methoden in C# haben, verwende ich die Delegierten vieles mehr. In C# 1, wo Sie immer eine separate Methode zur Implementierung der Logik benötigten, war die Verwendung eines Delegaten oft nicht sinnvoll. In diesen Tagen ich Delegierten für:

  • Eventhandler (für GUI und mehr)
  • Start Themen
  • Rückrufe (zB für Asynchron-APIs)
  • LINQ und ähnliche (List.Find etc)
  • Überall sonst, wo ich effektiv innen „Vorlage“ Code mit einigen spezialisierten Logik anwenden möchten (wo der Delegat die Spezialisierung bietet)
+0

Erwähnenswert die "Push" in Push LINQ? –

+3

Nicht sicher, wie ich es kurz erklären würde, ohne die Dinge verwirrender zu machen :) (Wahrscheinlich ist es von Event-Handlern, LINQ und dem Templaty-Bit sowieso abgedeckt! –

+1

Ihr erster Satz macht nicht viel Sinn. – senfo

4

abonnieren Eventhandler, an Veranstaltungen

0
  1. für Parameter Ereignisbehandlungsroutine

  2. die Methode bei einem Verfahren geben

0

Die erste Zeile der Verwendung ist die Beobachter/Observable (Ereignisse) Muster zu ersetzen. Die zweite, eine schöne, elegante Version des Strategy-Musters. Verschiedene andere Nutzungen können gesammelt werden, obwohl es mehr esoterisch als diese ersten zwei denke.

0

Veranstaltungen, andere anynch Operationen

0

Jedes Mal, wenn das Verhalten wollen, kapseln, aber es in einer einheitlichen Art und Weise aufrufen. Event-Handler, Call-Back-Funktionen, etc. Sie können ähnliche Dinge mit Interfaces und Umwandlungen erreichen, aber manchmal ist das Verhalten nicht notwendigerweise mit einem Typ oder Objekt verbunden. Manchmal haben Sie nur Verhalten, das Sie einkapseln müssen.

0

Lazy Parameter Initialisierung! Neben allen vorherigen Antworten (Strategie-Muster, Beobachter-Muster usw.) können Sie mit delegierten Parametern arbeiten. Angenommen, Sie haben eine Funktion Download(), die ziemlich viel Zeit in Anspruch nimmt und ein bestimmtes DownloadedObject zurückgibt. Dieses Objekt wird von einem Storage abhängig von bestimmten Bedingungen verbraucht. Normalerweise würden Sie:

storage.Store(conditions, Download(item)) 

jedoch mit Delegierten (genauer lambdas) können Sie die folgenden Aktionen durchführen, durch die Unterschrift des Speichers ändern, dass er einen Zustand und eine Func < Artikel erhält, DownloadedObject > und Verwendung es wie folgt aus:

storage.Store(conditions, (item) => Download(item)) 

Daher Speicher wertet nur die Delegierten, falls erforderlich, Download Ausführung abhängig von den Bedingungen.

+0

Minor Punkt, aber re "genauer gesagt, lambdas" - Sie könnten das gleiche mit einer anonymen Methode in C# 2.0 tun, obwohl es mehr v wäre erbose: delegate (ItemType item) {[return] Download (item);} –

+0

Sicher, wie LINQ: lambdas sind nichts anderes als syntaktischer Zucker für Delegierte. Sie haben die Delegierten einfach zugänglicher gemacht. –

+0

Lambdas sind etwas mehr als nur Delegaten, da sie sowohl in Ausdrucksbäume als auch in Delegaten konvertiert werden können. –

5

Eine etwas andere Verwendung ist es, die Reflexion zu beschleunigen; d. h., anstatt jedes Mal Reflektionen zu verwenden, können Sie Delegate.CreateDelegate verwenden, um einen (typisierten) Delegaten für eine Methode (a MethodInfo) zu erstellen und stattdessen diesen Delegaten aufzurufen. Dies ist dann viel schneller pro Anruf, da die Prüfungen bereits durchgeführt wurden.

Mit Expression, können Sie auch das gleiche tun Code on the fly erstellen - zum Beispiel, können Sie leicht ein Expression erstellen, die den Operator + für einen Typen zur Laufzeit gewählt darstellt (Bedienerunterstützung für Generika zur Verfügung zu stellen, die die Sprache bietet nicht); und Sie können eine Expression zu einem typisierten Delegierten kompilieren - Arbeit erledigt.

12

Sie können Delegaten verwenden, um funktionstypisierte Variablen und Parameter zu deklarieren.

Beispiel

Betrachten wir das Muster "resource Borgen". Sie möchten die Erstellung und Bereinigung einer Ressource steuern, während der Client-Code die Ressource dazwischen "ausborgen" kann.

Dies deklariert einen Delegattyp.

Jede Methode, die dieser Signatur entspricht, kann verwendet werden, um einen Delegaten dieses Typs zu instanziieren. In C# 2.0 kann dies implizit erfolgen, indem einfach der Name der Methode verwendet wird und anonyme Methoden verwendet werden.

Diese Methode verwendet den Typ als Parameter. Notieren Sie den Aufruf des Delegaten.

public class DataProvider 
{ 
    protected string _connectionString; 

    public DataProvider(string psConnectionString) 
    { 
     _connectionString = psConnectionString; 
    } 

    public void UseReader(string psSELECT, DataReaderUser readerUser) 
    { 
     using (SqlConnection connection = new SqlConnection(_connectionString)) 
     try 
     { 
      SqlCommand command = new SqlCommand(psSELECT, connection); 
      connection.Open(); 
      SqlDataReader reader = command.ExecuteReader(); 

      while (reader.Read()) 
       readerUser(reader); // the delegate is invoked 
     } 
     catch (System.Exception ex) 
     { 
      // handle exception 
      throw ex; 
     } 
    } 
} 

Die Funktion kann wie folgt mit einer anonymen Methode aufgerufen werden. Beachten Sie, dass die anonyme Methode die Variablen außerhalb von von sich selbst verwenden kann. Dies ist äußerst praktisch (obwohl das Beispiel ein wenig erfunden ist).

string sTableName = "test"; 
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'"; 

DataProvider.UseReader(sQuery, 
    delegate(System.Data.IDataReader reader) 
    { 
     Console.WriteLine(sTableName + "." + reader[0]); 
    }); 
0

Verwendung von Delegierten

  1. Ereignisbehandlung
  2. Multi Casting
0

Der Vergleich in param In Array.Sort (T [] array, Vergleich Vergleich), List.Sort (Vergleichsvergleich), usw.

13

Eine weitere interessante Antwort gefunden:

Ein Mitarbeiter hat mir gerade diese Frage gestellt - was ist der Punkt der Delegierten in .NET? Meine Antwort war sehr kurz und eine, die er online nicht gefunden hatte: die Ausführung einer Methode zu verzögern.

Quelle: LosTechies

Genau wie LINQ tut.

+0

+ 1..hatte nicht so darüber nachgedacht. Guter Punkt – Luke101

1

Ich benutze Delegaten, um mit Threads zu kommunizieren.

Zum Beispiel könnte ich eine Win Forms App haben, die eine Datei herunterlädt. Die App startet einen Worker-Thread, um den Download durchzuführen (wodurch verhindert wird, dass die GUI gesperrt wird). Der Worker-Thread verwendet Delegaten, um Statusnachrichten (z. B. Download-Fortschritt) an das Hauptprogramm zu senden, sodass die GUI die Statusleiste aktualisieren kann.

27

Delegaten sind sehr nützlich für viele Zwecke.

Ein solcher Zweck ist, um sie für die Folgen von Datenfiltern. In diesem Fall würden Sie einen Prädikat-Delegaten verwenden, der ein Argument akzeptiert und Wahr oder Falsch zurückgibt, abhängig von der Implementierung des Delegaten.

Hier ist ein dummes Beispiel - ich bin sicher, dass Sie etwas nützlicher aus diesem extrapolieren können:

using System; 
using System.Linq; 
using System.Collections.Generic; 

class Program 
{ 
    static void Main() 
    { 
     List<String> names = new List<String> 
     { 
      "Nicole Hare", 
      "Michael Hare", 
      "Joe Hare", 
      "Sammy Hare", 
      "George Washington", 
     }; 

     // Here I am passing "inMyFamily" to the "Where" extension method 
     // on my List<String>. The C# compiler automatically creates 
     // a delegate instance for me. 
     IEnumerable<String> myFamily = names.Where(inMyFamily); 

     foreach (String name in myFamily) 
      Console.WriteLine(name); 
    } 

    static Boolean inMyFamily(String name) 
    { 
     return name.EndsWith("Hare"); 
    } 
} 
+4

wo ist der Delegierte? –

+11

Die Methode 'static Boolean inMyFamily (String name)' ist der Delegat. Wo nimmt ein Delegat als Parameter. Da delegates nur Funktionszeiger sind, wenn Sie den Methodennamen in das '.Where (delegate)' übergeben, das zum Delegaten wird. Da inMyFamily einen booleschen Typ zurückgibt, wird es tatsächlich als Prädikat betrachtet. Prädikate sind nur Delegaten, die boolesche Werte zurückgeben. –

+4

"Prädikate sind nur Delegaten, die boolesche Werte zurückgeben." +1 – daehaai

5

Delegierten verwendet werden, wann immer Sie Ereignisse verwenden - das ist der Mechanismus, mit dem sie arbeiten.

Darüber hinaus sind die Delegierten sehr nützlich für Dinge wie LINQ-Abfragen verwendet wird. Zum Beispiel nehmen viele LINQ-Abfragen einen Delegaten (oft Func<T,TResult>), der zum Filtern verwendet werden kann.

10

Die Delegierten können oft anstelle einer Schnittstelle mit einem Verfahren wird ein gängiges Beispiel hierfür wäre die Beobachter-Muster sein, verwendet werden. In anderen Sprachen möchten, wenn Sie eine Benachrichtigung erhalten, dass etwas passiert ist Sie so etwas wie definieren könnte:

class IObserver{ void Notify(...); } 

in C# ist dies ausgedrückt häufig Ereignisse verwendet, wobei der Handler ein Delegierter ist, zum Beispiel:

myObject.SomeEvent += delegate{ Console.WriteLine("..."); }; 

ein weiterer großartiger Ort verwenden Delegierten, wenn, wenn Sie ein Prädikat in eine Funktion übergeben müssen, wenn beispielsweise eine Reihe von Elementen aus einer Liste auswählen:

myList.Where(i => i > 10); 

Die obige ist ein Beispiel für die Lambda-Syntax, die auch wie folgt geschrieben haben könnte:

myList.Where(delegate(int i){ return i > 10; }); 

Ein weiterer Ort, wo es sinnvoll sein kann, die Delegierten zu verwenden Fabrik Funktionen, zum Beispiel registrieren:

myFactory.RegisterFactory(Widgets.Foo,() => new FooWidget()); 
var widget = myFactory.BuildWidget(Widgets.Foo); 

Ich hoffe, das hilft!

+0

Schöne Beispiele mit Syntax .. Danke .. :) – Raghu

0

Soweit ich weiß, können Delegaten in Funktionszeiger umgewandelt werden. Dies macht das Leben VIEL einfacher, wenn es mit nativem Code interagiert, der Funktionszeiger verwendet, da sie effektiv objektorientiert sein können, obwohl der ursprüngliche Programmierer dafür keine Vorkehrungen getroffen hat.

0

Delegierten werden verwendet, um eine Methode aufzurufen, indem es Bezug ist. Zum Beispiel:

delegate void del_(int no1,int no2); 
class Math 
{ 
    public static void add(int x,int y) 
    { 
    Console.WriteLine(x+y); 
    } 
    public static void sub(int x,int y) 
    { 
    Console.WriteLine(x-y); 
    } 
} 



    class Program 
    { 
     static void Main(string[] args) 
     { 
      del_ d1 = new del_(Math.add); 
      d1(10, 20); 
      del_ d2 = new del_(Math.sub); 
      d2(20, 10); 
      Console.ReadKey(); 
     } 
    } 
10

Ich komme auf das wirklich spät, aber ich hatte Schwierigkeiten, heute den Zweck der Delegierten herauszufinden, und schrieb zwei einfache Programme, die die gleiche Leistung geben, dass ich glaube, ihren Zweck gut erklärt.

NoDelegates.cs

using System; 

public class Test { 
    public const int MAX_VALUE = 255; 
    public const int MIN_VALUE = 10; 

    public static void checkInt(int a) { 
     Console.Write("checkInt result of {0}: ", a); 
     if (a < MAX_VALUE && a > MIN_VALUE) 
      Console.WriteLine("max and min value is valid"); 
     else 
      Console.WriteLine("max and min value is not valid"); 
    } 

    public static void checkMax(int a) { 
     Console.Write("checkMax result of {0}: ", a); 
     if (a < MAX_VALUE) 
      Console.WriteLine("max value is valid"); 
     else 
      Console.WriteLine("max value is not valid"); 
    } 

    public static void checkMin(int a) { 
     Console.Write("checkMin result of {0}: ", a); 
     if (a > MIN_VALUE) 
      Console.WriteLine("min value is valid"); 
     else 
      Console.WriteLine("min value is not valid"); 
     Console.WriteLine(""); 
    } 
} 

public class Driver { 
    public static void Main(string [] args) { 
     Test.checkInt(1); 
     Test.checkMax(1); 
     Test.checkMin(1); 

     Test.checkInt(10); 
     Test.checkMax(10); 
     Test.checkMin(10); 

     Test.checkInt(20); 
     Test.checkMax(20); 
     Test.checkMin(20); 

     Test.checkInt(30); 
     Test.checkMax(30); 
     Test.checkMin(30); 

     Test.checkInt(254); 
     Test.checkMax(254); 
     Test.checkMin(254); 

     Test.checkInt(255); 
     Test.checkMax(255); 
     Test.checkMin(255); 

     Test.checkInt(256); 
     Test.checkMax(256); 
     Test.checkMin(256); 
    } 
} 

Delegates.cs

using System; 

public delegate void Valid(int a); 

public class Test { 
    public const int MAX_VALUE = 255; 
    public const int MIN_VALUE = 10; 

    public static void checkInt(int a) { 
     Console.Write("checkInt result of {0}: ", a); 
     if (a < MAX_VALUE && a > MIN_VALUE) 
      Console.WriteLine("max and min value is valid"); 
     else 
      Console.WriteLine("max and min value is not valid"); 
    } 

    public static void checkMax(int a) { 
     Console.Write("checkMax result of {0}: ", a); 
     if (a < MAX_VALUE) 
      Console.WriteLine("max value is valid"); 
     else 
      Console.WriteLine("max value is not valid"); 
    } 

    public static void checkMin(int a) { 
     Console.Write("checkMin result of {0}: ", a); 
     if (a > MIN_VALUE) 
      Console.WriteLine("min value is valid"); 
     else 
      Console.WriteLine("min value is not valid"); 
     Console.WriteLine(""); 
    } 
} 

public class Driver { 
    public static void Main(string [] args) { 
     Valid v1 = new Valid(Test.checkInt); 
     v1 += new Valid(Test.checkMax); 
     v1 += new Valid(Test.checkMin); 
     v1(1); 
     v1(10); 
     v1(20); 
     v1(30); 
     v1(254); 
     v1(255); 
     v1(256); 
    } 
} 
2

Ein Beispiel könnte als here zu sehen. Sie haben eine Methode, um ein Objekt zu verarbeiten, das bestimmte Anforderungen erfüllt. Sie möchten das Objekt jedoch auf mehrere Arten verarbeiten können.Anstatt separate Methoden zu erstellen, können Sie einfach eine übereinstimmende Methode zuweisen, die das Objekt zu einem Delegaten verarbeitet, und den Delegaten an die Methode übergeben, die die Objekte auswählt. Auf diese Weise können Sie der One-Selector-Methode verschiedene Methoden zuweisen. Ich habe versucht, das leicht verständlich zu machen.

Verwandte Themen