Ich bin auf eine Situation gestoßen, in der ich etwas Wissen brauche.
Unten ist der Code:
%Vor% Mein Verständnis von Action
war, dass es mit einem Delegaten übereinstimmt, der keinen Parameter akzeptiert und nichts zurückgibt.
Und für Func<int>
, dass es mit einem Delegaten übereinstimmt, der keinen Parameter akzeptiert und ein int
zurückgibt.
DoSomething
Methode gibt eine ganze Zahl zurück, daher meine Frage: () => DoSomething()
ist ein Delegat, das ein int
zurückgibt. Func
funktioniert wie erwartet, Action
jedoch nicht. Warum? Was verstehe ich hier nicht?
Der Code wird kompiliert und läuft ordnungsgemäß, beide Ausgaben i am called
. Was ich wissen möchte, ist, warum Action action = () => DoSomething();
ist kein Fehler Kompilierzeit?
Was ich wissen möchte ist, dass
Action action = () => DoSomething();
kein Kompilierzeitfehler ist?
Es kompiliert, weil Sie einen Lambda-Ausdruck haben, der die Methode aufruft, aber das Ergebnis ignoriert. Sie können keine Methodengruppenkonvertierung verwenden, z. B.
%Vor% (Die Konvertierung der gleichen Methodengruppe für Func<Action, int>
ist in Ordnung.)
Aber stattdessen machst du etwas mehr so:
%Vor% Der C # -Compiler ist schlau genug, um herauszufinden, dass () => DoSomething()
je nach Kontext unterschiedliche Dinge bedeutet. Wenn Sie eine Action
Variable zuweisen, wird eine Action
(anstelle von Func<int>
) generiert, die das Rückgabeergebnis von DoSomething()
ignoriert.
DoSomething
Methode gibt eine ganze Zahl zurück, daher meine Frage:(x) => DoSomething(x)
ist ein Delegat, der einobject
akzeptiert und einint
zurückgibt.Func
funktioniert wie erwartet,Action
jedoch nicht. Warum? Was verstehe ich hier nicht?
Der Fehler in Ihrem Verständnis ist hier richtig: (x) => DoSomething(x)
hat keinen Typ. Es ist nichts. Der Compiler benötigt einen Kontext, um herauszufinden, um welchen Typ es sich handelt. Für sich genommen ist ein Lambda nichts Besonderes, deshalb können Sie var
nicht mit einem Lambda-Ausdruck verwenden: Der Compiler weiß nicht, welchen Typ das Lambda haben soll, damit er den Typ nicht ableiten kann.
Zum Beispiel könnte (x) => DoSomething(x)
auch ein Ausdrucksbaum sein:
Sie sagen dem Compiler also, wie Sie ein Lambda basierend auf dem Typ, dem Sie es zuweisen, interpretieren.
Ihr ganzes Verständnis ist richtig. Es ist Ihre spezifische Verwendung, die zu Verwirrung führen kann. Sowohl Func als auch Action sind in Ordnung. Beide Anrufe sind in Ordnung. Ich denke, der Fall, der Ihr Problem beleuchten könnte, ist:
var x = action(5); // NOT ok
var y = func(5); // ok
Ihr Beispielcode ignoriert nur den Rückgabewert, weshalb es so aussieht, als wären sie gleich. Nicht anders als
void Foo1(int x) { return; }
void Foo2(int x) { return 1; }
Foo1(5);
Foo2(5);