Was ist der Unterschied zwischen Func <string, string> und delegate?


79

Ich sehe Delegierte in zwei Formen:

A. Func<string, string> convertMethod = lambda 

B. public delegate string convertMethod(string value);

Ich bin mir nicht sicher, was der Unterschied zwischen diesen beiden ist. Sind sie beide Delegierte? Ich glaube, der erste würde ein Lambda verwenden und der zweite müsste eine Methode haben, um die Arbeit tatsächlich auszuführen. Ich kann auch verwirrt sein.


Antworten:


72

Zunächst machen Ihre beiden Beispiele zwei völlig getrennte Dinge. Die erste deklariert eine generische Delegatenvariable und weist ihr einen Wert zu, die zweite definiert lediglich einen delegateTyp. Ihr Beispiel wäre vollständiger:

public static class Program
{
    // you can define your own delegate for a nice meaningful name, but the
    // generic delegates (Func, Action, Predicate) are all defined already
    public delegate string ConvertedMethod(string value);

    public static void Main()
    {
        // both work fine for taking methods, lambdas, etc.
        Func<string, string> convertedMethod = s => s + ", Hello!";
        ConvertedMethod convertedMethod2 = s => s + ", Hello!";
    }
}

Aber mehr auf den Punkt, beide Func<string,string>und delegate string convertMethod(string)wären in der Lage, die gleichen Methodendefinitionen zu halten, egal ob es sich um Methoden, anonyme Methoden oder Lambda-Ausdrücke handelt.

Was Sie verwenden sollten, hängt von der Situation ab. Wenn Sie möchten, dass Ihr Delegat mehr durch das definiert wird, was er benötigt und zurückgibt, sind die generischen Delegaten perfekt. Wenn Sie die Delegierten wollen einige spezielle Namen zu haben , die mehr Definition dessen , was tun , dass Delegierte gibt sollte (über einfache Action, Predicateetc) , dann Ihre eigenen Delegierten schaffen , ist immer eine Option.


1
Ein noch klareres Beispiel wäre Func<int, string>, das zeigt, dass die Form ist Func<arg1, result>.
Silvalli

5
Ich denke, es ist erwähnenswert, dass Func und Action Delegierte sind. Es scheint offensichtlich, wenn Sie es wissen, aber ich war über diese Tatsache ausgeflippt, bevor ich mir die Unterschrift von Func ansah. Wenn Sie also sagen: "Zunächst einmal machen Ihre beiden Beispiele zwei völlig getrennte Dinge." man könnte auch sagen: "Func ist ein Delegierter".
Falk

12

Das Codebeispiel, das Sie haben, ist etwas verwirrend. Lassen Sie mich versuchen, es zu klären. Die folgenden 2 Elemente sind Delegiertenerklärungen. Diese sind leicht zu erkennen, da sie immer das delegateSchlüsselwort enthalten

public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);

Diese Codezeile weist einem lokalen Wert einen Wert zu, der einem Delegaten eingegeben wird

Func<string, string> local = lambda;

Der obige Code ist jedoch nicht auf die Verwendung von nur Lambdas beschränkt. Der Wert kann auch eine kompatible Methodengruppe oder ein anderer Delegatenwert sein.

Ein weiterer Punkt zu beachten ist , dass obwohl Func<string, string>und convertMethodsind beiden Teilnehmer mit identischen Signaturen ihre Werte sind nicht miteinander konvertierbar. Zum Beispiel ist das Folgende illegal

Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!

8

Von MSDN ,

In Versionen von C # vor 2.0 bestand die einzige Möglichkeit, einen Delegaten zu deklarieren, darin, benannte Methoden zu verwenden. In C # 2.0 wurden anonyme Methoden eingeführt, und in C # 3.0 und höher ersetzen Lambda-Ausdrücke anonyme Methoden als bevorzugte Methode zum Schreiben von Inline-Code.

und

Es gibt einen Fall, in dem eine anonyme Methode Funktionen bereitstellt, die in Lambda-Ausdrücken nicht enthalten sind. Mit anonymen Methoden können Sie die Parameterliste weglassen. Dies bedeutet, dass eine anonyme Methode in Delegate mit verschiedenen Signaturen konvertiert werden kann.

Diese SO-Antwort auf das Schlüsselwort delegate vs lambda expression könnte Sie auch interessieren .

Darüber hinaus hat MSDN einen guten Artikel über Lambda Expressions :

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

Beachten Sie im vorherigen Beispiel, dass die Delegatensignatur einen implizit typisierten Eingabeparameter vom Typ int enthält und ein int zurückgibt. Der Lambda-Ausdruck kann in einen Delegaten dieses Typs konvertiert werden, da er auch einen Eingabeparameter (x) und einen Rückgabewert enthält, den der Compiler implizit in den Typ int konvertieren kann. (Die Typinferenz wird in den folgenden Abschnitten ausführlicher erläutert.) Wenn der Delegat mit einem Eingabeparameter von 5 aufgerufen wird, wird ein Ergebnis von 25 zurückgegeben.


Sie können auch Parameter aus Lambda weglassen. () => Console.Writeline ("Parameter weniger Lambda")
Dr. Deo

Aktionstest = () => Console.Writeline ("Parameter weniger Lambda"); test.Invoke ();
Dr. Deo

5

A initialisiert eine Instanz eines Delegaten (die sofort aufgerufen werden kann). Es ist eine Variable vom Typ Func <string, string>.

B gibt die Definition eines Delegaten (seine Signatur) an. Es kann verwendet werden, um später Variablen vom Typ convertMethod zu definieren .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.