Es gibt zwei Dinge, die Sie wissen müssen, um dieses Verhalten zu verstehen.
- Alle Delegierten stammen von ab
System.Delegate
, aber unterschiedliche Delegierte haben unterschiedliche Typen und können daher nicht einander zugewiesen werden.
- Die C # -Sprache bietet eine spezielle Behandlung für die Zuweisung einer Methode oder eines Lambda zu einem Delegaten .
Da verschiedene Delegaten unterschiedliche Typen haben, können Sie einen Delegaten eines Typs keinem anderen zuweisen.
Zum Beispiel gegeben:
delegate void test1(int i);
delegate void test2(int i);
Dann:
test1 a = Console.WriteLine; // Using special delegate initialisation handling.
test2 b = a; // Using normal assignment, therefore does not compile.
In der ersten Zeile oben wird OK kompiliert, da die spezielle Behandlung zum Zuweisen eines Lambda oder einer Methode zu einem Delegaten verwendet wird.
Tatsächlich wird diese Zeile vom Compiler effektiv wie folgt umgeschrieben:
test1 a = new test1(Console.WriteLine);
Die zweite Zeile oben wird nicht kompiliert, da versucht wird, eine Instanz eines Typs einem anderen inkompatiblen Typ zuzuweisen.
Was die Typen betrifft, gibt es keine kompatible Zuordnung zwischen test1
und, test2
da es sich um verschiedene Typen handelt.
Wenn es hilfreich ist, darüber nachzudenken, berücksichtigen Sie diese Klassenhierarchie:
class Base
{
}
class Test1 : Base
{
}
class Test2 : Base
{
}
Der folgende Code wird nicht kompiliert, obwohl Test1
und Test2
stammt aus der gleichen Basisklasse:
Test1 test1 = new Test1();
Test2 test2 = test1; // Compile error.
Dies erklärt, warum Sie einen Delegatentyp keinem anderen zuweisen können. Das ist nur die normale C # -Sprache.
Entscheidend ist jedoch, zu verstehen, warum Sie einem kompatiblen Delegaten eine Methode oder ein Lambda zuweisen dürfen. Wie oben erwähnt, ist dies Teil der C # -Sprachenunterstützung für Delegierte.
Also endlich um deine Frage zu beantworten:
Wenn Sie verwenden Invoke()
, weisen Sie dem Delegaten einen METHOD-Aufruf zu, indem Sie die spezielle C # -Sprachenbehandlung verwenden, um einem Delegaten Methoden oder Lambdas zuzuweisen, anstatt zu versuchen, einen inkompatiblen Typ zuzuweisen. Daher wird OK kompiliert.
Um ganz klar zu sein, der Code, der in Ihrem OP kompiliert wird:
public test Success()
{
Func<int, int> f = x => x;
return f.Invoke; // <- code successfully compiled
}
Wird tatsächlich konzeptionell in etwas umgewandelt wie:
public test Success()
{
Func<int, int> f = x => x;
return new test(f.Invoke);
}
Während der fehlerhafte Code versucht, zwischen zwei inkompatiblen Typen zuzuweisen:
public test Fail()
{
Func<int, int> f = x => x;
return f; // Attempting to assign one delegate type to another: Fails
}