Frage

Diese Frage wird mir oft gestellt, und ich dachte, ich frage mich, wie ich den Unterschied am besten beschreiben kann.

War es hilfreich?

Lösung

Sie sind eigentlich zwei sehr verschiedene Dinge. „Delegieren“ ist eigentlich der Name für eine Variable, die einen Verweis auf ein Verfahren oder ein Lambda hält, und eine Lambda ist ein Verfahren ohne permanente Namen.

Lambdas sind sehr ähnlich wie andere Methoden, mit Ausnahme von ein paar feinen Unterschieden.

  1. Ein normales Verfahren in einem „Anweisung“ und gebunden an einem dauerhaften nennen, während ein Lambda ist definiert "on the fly" in einem "Expression" und keinen Namen hat.
  2. kann Einige lambdas mit .NET Ausdrucksbäume verwendet werden, während Methoden nicht.

Ein Delegierter ist definiert wie folgt:

delegate Int32 BinaryIntOp(Int32 x, Int32 y);

Eine Variable vom Typ BinaryIntOp haben kann entweder ein Verfahren oder eine labmda ihm zugeordneten, solange die Signatur ist das gleiche:. Int32 zwei Argumente und einen int32

Ein Lambda könnte wie folgt definiert werden:

BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;

Eine andere Sache zu beachten ist, dass, obwohl die allgemeine Func und Action-Typen oft als „Lambda-Typen“ betrachtet werden, sie genauso wie alle anderen Delegierten sind. Das Schöne daran ist, dass sie im Wesentlichen einen Namen für jede Art von Delegaten definieren Sie (bis zu 4 Parametern, obwohl Sie sicherlich mehr von Ihrer eigenen hinzufügen können) benötigen. Also, wenn Sie eine große Auswahl an Delegattypen verwenden, aber nicht mehr als einmal, können Sie Ihren Code mit Delegierten Erklärungen unübersichtlich vermeiden, indem Func und Aktion verwendet wird.

Hier ist ein Beispiel dafür, wie Func und Aktion ist „nicht nur für die Lambda-Ausdrücke“:

Int32 DiffOfSquares(Int32 x, Int32 y)
{
  return x*x - y*y;
}

Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;

Eine andere nützliche Sache zu wissen ist, dass Delegattypen (diese Methoden nicht selbst) mit der gleichen Signatur aber verschiedene Namen werden nicht implizit miteinander gegossen werden. Dazu gehören auch die Func und Action-Delegierten. Wenn jedoch die Unterschrift identisch ist, können Sie explizit zwischen ihnen werfen.

Gehen die extra Meile .... In C # Funktionen sind flexibel, mit der Verwendung von Lambda-Ausdrücke und Delegierten. Aber C # nicht über "First-Class-Funktionen". Sie können eine Funktion des Namens einer Delegate-Variablen zugewiesen verwenden, um im wesentlichen ein Objekt zu erstellen, um diese Funktion darstellt. Aber es ist wirklich ein Compiler-Trick. Wenn Sie eine Anweisung starten, indem Sie den Funktionsnamen gefolgt von einem Punkt zu schreiben (das heißt versuchen Mitglied Zugriff auf die Funktion selbst zu tun) werden Sie feststellen, gibt es keine Mitglieder Referenz. Nicht einmal die, die von Object. Dies verhindert, dass der Programmierer zu tun, nützliche (und potenziell gefährliche natürlich) Dinge wie Erweiterungsmethoden hinzufügen, die auf einem beliebigen Funktion aufgerufen werden können. Das Beste, was Sie tun können, ist die Delegate-Klasse erweitert sich, die sicherlich auch nützlich, aber nicht ganz so viel.

Update: Siehe auch Karg Antwort den Unterschied zwischen anonym Delegierten darstellen vs. Methoden und Lambda-Ausdrücke.

Update 2: James Hart ein wichtiger macht, wenn auch sehr technisch, dass lambdas zu beachten und die Delegierten sind nicht .NET Einheiten (dh die CLR hat kein Konzept eines Delegierten oder Lambda), sondern sie sind Rahmen und Sprachkonstrukte.

Andere Tipps

Die Frage ist ein wenig zweideutig, was die großen Unterschiede in den Antworten erklären Sie bekommen.

Sie tatsächlich gefragt, was der Unterschied zwischen lambda und Delegierten in dem .NET-Framework ist; das könnte ein von einer Reihe von Dingen. Sind Sie fragen:

  • Was ist der Unterschied zwischen Lambda-Ausdrücke und anonymen Teilnehmern in der C # (oder VB.NET) Sprache ist?

  • Was ist der Unterschied zwischen System.Linq.Expressions.LambdaExpression Objekten und System.Delegate Objekten in .NET 3.5?

  • Oder etwas irgendwo zwischen oder um diese Extreme?

Einige Leute scheinen zu versuchen, Sie auf die Frage, um die Antwort zu geben: ‚Was ist der Unterschied zwischen C # Lambda-Ausdrücke und .NET System.Delegate?‘, Die nicht eine ganze Menge Sinn macht.

Der .NET-Framework ist für sich genommen nicht die Konzepte der anonym Delegierten, Lambda-Ausdrücke oder Verschlüsse verstehen - das alles von Sprachspezifikationen definiert ist. Denken Sie darüber nach, wie der C # -Compiler die Definition eines anonymen Verfahren in ein Verfahren auf einer generierten Klasse mit Membervariablen übersetzt Schließzustand zu halten; .NET, gibt es nichts, die Delegierten anonym über; es ist nur anonym an die # Programmierer C schreiben sie. Das ist ebenso wahr, von einem Lambda-Ausdruck in einen Delegate-Typ zugeordnet.

Was .NET DOES verstehen die Idee eines Delegierten ist - ein Typ, der eine Methodensignatur, Instanzen, von denen auf bestimmte Objekte repräsentieren entweder gebunden Anrufe an bestimmte Methoden beschreibt, oder ungebundenen Anrufe zu einem bestimmten Verfahren auf einen bestimmten Typ, die gegen jedes Objekt dieses Typs aufgerufen werden kann, wobei das Verfahren zu der genannten Signatur haftet. Solche Typen erben alle von System.Delegate.

.NET 3.5 führt auch die System.Linq.Expressions Namespace, die Klassen für die Beschreibung Code Ausdrücke enthält - und das auch deshalb gebunden oder ungebunden Aufrufe von Methoden auf bestimmten Typen oder Objekten darstellen kann. Lambda Fällen kann dann in tatsächlichen Teilnehmer zusammengestellt werden (wobei eine dynamische Methode auf die Struktur des Expressions basiert codegenned und einen Delegierten Zeiger darauf zurückgeführt).

In C # Sie Instanzen von System.Expressions.Expression Typen durch einen Lambda-Ausdruck Zuordnung zu einer Variablen des Typs erzeugen können, die den entsprechenden Code erzeugen den Ausdruck zur Laufzeit zu konstruieren.

Natürlich, wenn Sie wurde zu fragen, was der Unterschied zwischen Lambda-Ausdrücke und anonymen Methoden in C # ist, nach allem, dann all dies ist so ziemlich irelevant, und in diesem Fall ist die Hauptunterschied Kürze ist , die auf anonyme Teilnehmer lehnt sich, wenn Sie Parameter nicht kümmern und nicht planen, einen Wert auf Rückkehr und in Richtung lambdas wenn Sie an Typ inferiert Parameter und Rückgabetypen wollen.

Und Lambda-Ausdrücke unterstützt Ausdruck Generation.

Ein Unterschied besteht darin, dass ein anonymer Delegat Parameter weglassen kann, während eine Lambda die genaue Signatur übereinstimmen muss. Gegeben:

public delegate string TestDelegate(int i);

public void Test(TestDelegate d)
{}

Sie können es in den folgenden vier Arten aufrufen (beachten Sie, dass die zweite Zeile einen anonymen Delegierten hat, die keine Parameter haben):

Test(delegate(int i) { return String.Empty; });
Test(delegate { return String.Empty; });
Test(i => String.Empty);
Test(D);

private string D(int i)
{
    return String.Empty;
}

Sie können nicht in einem Lambda-Ausdruck übergeben, die keine Parameter oder eine Methode, die keine Parameter hat. Diese sind nicht zulässig:

Test(() => String.Empty); //Not allowed, lambda must match signature
Test(D2); //Not allowed, method must match signature

private string D2()
{
    return String.Empty;
}

Die Delegierten sind äquivalent zu Funktionszeiger / Methodenzeiger / Rückrufe (nehmen Sie Ihre Wahl) und Lambda-Ausdrücke sind so ziemlich anonyme Funktionen vereinfacht. Zumindest ist das, was ich den Leuten sagen.

Ich habe nicht eine Tonne Erfahrung mit diesem, aber die Art, wie ich es beschreiben würde, ist, dass ein Delegierter ein Wrapper um jede Funktion ist, während ein Lambda-Ausdruck ist selbst eine anonyme Funktion.

Ein Delegierter ist immer im Grunde nur ein Funktionszeiger. Ein Lambda kann in einen Delegaten drehen, aber es kann auch einen LINQ Ausdrucksbaum verwandeln. Zum Beispiel

Func<int, int> f = x => x + 1;
Expression<Func<int, int>> exprTree = x => x + 1;

Die erste Zeile erzeugt einen Vertreter, während die zweiten einen Ausdrucksbaum erzeugt.

lambdas sind einfach syntaktischer Zucker auf einem Delegierten. Der Compiler endet lambdas in Delegierten zu konvertieren.

Dies sind die gleichen, wie ich glaube:

Delegate delegate = x => "hi!";
Delegate delegate = delegate(object x) { return "hi";};

Ein Delegierter ist eine Funktion Signatur; so etwas wie

delegate string MyDelegate(int param1);

Der Beauftragte implementieren keinen Körper.

Das Lambda ist ein Funktionsaufruf, der die Signatur des Delegaten übereinstimmt. Für die oben delegieren könnte verwenden Sie irgendwelche;

(int i) => i.ToString();
(int i) => "ignored i";
(int i) => "Step " + i.ToString() + " of 10";

Der Delegate Typ ist schlecht benannt, obwohl; ein Objekt vom Typ Delegate Schaffung schafft tatsächlich eine Variable, welche Funktionen halten können -. aus den Bereichen lambdas, statische Methoden oder Methoden der Klasse

A delegieren ist ein Hinweis auf ein Verfahren mit einem bestimmten Parameterliste und Rückgabetyp. Es kann oder auch nicht ein Objekt umfassen.

Ein Lambda-Ausdruck ist eine Form der anonymen Funktion.

Es ist ziemlich klar, dass die Frage sein soll: „Was ist der Unterschied zwischen lambda und anonym Delegierten?“ Aus all den Antworten hier nur eine Person es richtig gemacht - die Hauptunterschied besteht darin, dass Lambda-Ausdrücke verwendet werden kann Ausdrucksbäume sowie Delegierten erstellen

.

Sie können mehr über MSDN lesen: http://msdn.microsoft.com /en-us/library/bb397687.aspx

Die Teilnehmer sind wirklich nur strukturelle Typisierung für Funktionen. Sie könnten das gleiche mit nominal Typisierung tun und eine anonyme Klasse implementieren, die eine Schnittstelle oder eine abstrakte Klasse implementiert, aber das endet eine Menge Code zu sein, wenn nur eine Funktion benötigt wird.

Lambda kommt von der Idee des Lambda-Kalkül von Alonzo Church in den 1930er Jahren. Es ist eine anonyme Art und Weise Funktionen zu schaffen. Sie werden besonders nützlich für das Komponieren Funktionen

So, während einige vielleicht sagen Lambda für die Delegierten syntaktischer Zucker ist, würde ich sagt Delegierten eine Brücke für die Menschen in lambdas in c # zu erleichtern.

Ein Delegat ist eine Warteschlange von Funktionszeigern. Der Aufruf eines Delegaten kann mehrere Methoden aufrufen.Ein Lambda ist im Wesentlichen eine anonyme Methodendeklaration, die vom Compiler unterschiedlich interpretiert werden kann, je nachdem, in welchem ​​Kontext sie verwendet wird.

Sie können einen Delegaten erhalten, der auf den Lambda-Ausdruck als Methode verweist, indem Sie ihn in einen Delegaten umwandeln. Wenn Sie ihn als Parameter an eine Methode übergeben, die einen bestimmten Delegatentyp erwartet, wandelt ihn der Compiler für Sie um.Wenn es innerhalb einer LINQ-Anweisung verwendet wird, wird das Lambda vom Compiler in einen Ausdrucksbaum übersetzt und nicht einfach in einen Delegaten.

Der Unterschied besteht tatsächlich darin, dass ein Lambda eine knappe Möglichkeit ist, eine Methode innerhalb eines anderen Ausdrucks zu definieren, während ein Delegat ein tatsächlicher Objekttyp ist.

Lambdas sind vereinfachte Versionen von Delegierten. Sie haben einige der die Eigenschaften eines Schließung wie anonyme Teilnehmer, sondern auch erlauben Sie implizite Typisierung zu verwenden. Ein Lambda wie folgt aus:

something.Sort((x, y) => return x.CompareTo(y));

ist viel knapper als das, was Sie mit einem Delegierten tun können:

something.Sort(sortMethod);
...

private int sortMethod(SomeType one, SomeType two)
{
    one.CompareTo(two)
}

Heres ein Beispiel, das ich eine Weile auf meinem lahmen Blog setzen. Sagen Sie ein Label von einem Worker-Thread aktualisieren wollen. Ich habe 4 Beispiele dafür, wie dieses Label von 1 bis 50 unter Verwendung von Delegierten, anon Delegierten und zwei Arten von Lambdas zu aktualisieren.

 private void button2_Click(object sender, EventArgs e) 
     { 
         BackgroundWorker worker = new BackgroundWorker(); 
         worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
         worker.RunWorkerAsync(); 
     } 

     private delegate void UpdateProgDelegate(int count); 
     private void UpdateText(int count) 
     { 
         if (this.lblTest.InvokeRequired) 
         { 
             UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); 
             this.Invoke(updateCallBack, new object[] { count }); 
         } 
         else 
         { 
             lblTest.Text = count.ToString(); 
         } 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     {   
         /* Old Skool delegate usage.  See above for delegate and method definitions */ 
         for (int i = 0; i < 50; i++) 
         { 
             UpdateText(i); 
             Thread.Sleep(50); 
         } 

         // Anonymous Method 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((MethodInvoker)(delegate() 
             { 
                 lblTest.Text = i.ToString(); 
             })); 
             Thread.Sleep(50); 
         } 

         /* Lambda using the new Func delegate. This lets us take in an int and 
          * return a string.  The last parameter is the return type. so 
          * So Func<int, string, double> would take in an int and a string 
          * and return a double.  count is our int parameter.*/ 
         Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke(UpdateProgress, i); 
             Thread.Sleep(50); 
         } 

         /* Finally we have a totally inline Lambda using the Action delegate 
          * Action is more or less the same as Func but it returns void. We could 
          * use it with parameters if we wanted to like this: 
          * Action<string> UpdateProgress = (count) => lblT…*/ 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); 
             Thread.Sleep(50); 
         } 
     }

Ich gehe davon aus, dass Ihre Frage betrifft c # und nicht .NET, wegen der Mehrdeutigkeit Ihrer Frage, wie .NET nicht allein erhalten - das heißt, ohne c # -. Verständnis der Delegierten und Lambda-Ausdrücke

A ( normale im Gegensatz zu sogenanntem generic Delegierten, cf später) Delegierten als eine Art c sollte ++ gesehen typedef von ein Funktionszeigertyp, beispielsweise in C ++:

R (*thefunctionpointer) ( T ) ;

typedef ist der Typ thefunctionpointer, die die Art des Zeigers auf eine Funktion ist ein Objekt vom Typ T nehmen und ein Objekt vom Typ R zurück. Sie würde es so verwenden:

thefunctionpointer = &thefunction ;
R r = (*thefunctionpointer) ( t ) ; // where t is of type T

wo thefunction wäre eine Funktion, um eine T zu nehmen und eine R zurück.

In c # würden Sie gehen für

delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed

, und Sie würden es wie folgt verwenden:

thedelegate thedel = thefunction ;
R r = thedel ( t ) ; // where t is of type T

wo thefunction wäre eine Funktion, um eine T zu nehmen und eine R zurück. Dies ist für die Teilnehmer, so normal Delegierten genannt.

Jetzt haben Sie auch generische Delegaten in c #, die Delegierten, die generisch sind, d. , die „Templat“ sind sozusagen mit dabei ein C ++ Ausdruck. Sie sind wie folgt definiert:

public delegate TResult Func<in T, out TResult>(T arg);

Und Sie können sie wie folgt verwendet:

Func<double, double> thefunctor = thefunction2; // call it a functor because it is
                                                // really as a functor that you should
                                                // "see" it
double y = thefunctor(2.0);

Dabei gilt thefunction2 eine Funktion als Argument zu nehmen und eine double zurück.

Nun stell dir vor, dass anstelle von thefunction2 würde Ich mag eine „Funktion“ zu verwenden, die für jetzt nirgends definiert ist, durch eine Erklärung, und das werde ich nie höher verwenden. Dann c # ermöglicht es uns, die Ausdruck von dieser Funktion zu verwenden. Mit dem Ausdruck meine ich den „mathematischen“ (oder funktional, um Programme zu bleiben) Ausdruck davon, zum Beispiel: zu einem double x wird ich Mitarbeiter die double x*x. In Mathe schreiben Sie diese mit href="https://math.stackexchange.com/questions/651205/regarding-the-notation-f-a-mapsto-b">. In c # die funktionale Notation entlehnt: =>. Zum Beispiel:

Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not
                                                           // mandatory

(double x) => x * x ist ein Ausdruck . Es ist kein Typ, während die Delegierten (generisch oder nicht) sind.

Morality? Am Ende, was ist ein Delegierter (resp. Generic Delegierter), wenn keine Funktion Zeigertyp (resp. Gewickelt + smart + generische Funktion Zeigertyp), nicht wahr? Etwas anderes ! Siehe diese und dass .

Einige hier einfach. „Delegate“ ist eigentlich der Name für eine Variable, die einen Verweis auf ein Verfahren oder eine Lambda

hält

Dies ist eine anonyme Methode -

(string testString) => { Console.WriteLine(testString); };

Als anonyme Methode keinen Namen haben wir einen Delegierten müssen, in dem wir beide dieser Methode oder Ausdruck zuweisen können. Für Ex.

delegate void PrintTestString(string testString); // declare a delegate

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; 
print();

Das gleiche mit dem Lambda-Ausdruck. Normalerweise brauchen wir delegieren, sie zu benutzen

s => s.Age > someValue && s.Age < someValue    // will return true/false

Wir können eine func delegieren verwenden diesen Ausdruck zu verwenden.

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

bool result = checkStudentAge ( Student Object);

Nun, die wirklich stark vereinfachte Version ist, dass ein Lambda nur eine Abkürzung für eine anonyme Funktion ist. Ein Delegierter kann viel mehr tun, als nur anonyme Funktionen. Dinge wie Ereignisse, asynchrone Aufrufe und mehr Verfahren Ketten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top