Il y a deux choses que vous devez savoir pour comprendre ce comportement.
- Tous les délégués dérivent de
System.Delegate
, mais différents délégués ont des types différents et ne peuvent donc pas être affectés les uns aux autres.
- Le langage C # fournit une gestion spéciale pour attribuer une méthode ou lambda à un délégué .
Étant donné que différents délégués ont des types différents, cela signifie que vous ne pouvez pas affecter un délégué d'un type à un autre.
Par exemple, étant donné:
delegate void test1(int i);
delegate void test2(int i);
Alors:
test1 a = Console.WriteLine; // Using special delegate initialisation handling.
test2 b = a; // Using normal assignment, therefore does not compile.
La première ligne ci-dessus compile OK car elle utilise la gestion spéciale pour affecter un lambda ou une méthode à un délégué.
En fait, cette ligne est effectivement réécrite comme ceci par le compilateur:
test1 a = new test1(Console.WriteLine);
La deuxième ligne ci-dessus ne se compile pas car elle essaie d'affecter une instance d'un type à un autre type incompatible.
En ce qui concerne les types, il n'y a pas d'affectation compatible entre test1
et test2
car ce sont des types différents.
Si cela aide à y penser, considérez cette hiérarchie de classes:
class Base
{
}
class Test1 : Base
{
}
class Test2 : Base
{
}
Le code suivant ne compile pas, même si Test1
et Test2
tirer de la même classe de base:
Test1 test1 = new Test1();
Test2 test2 = test1; // Compile error.
Cela explique pourquoi vous ne pouvez pas affecter un type de délégué à un autre. C'est juste le langage C # normal.
Cependant, la chose cruciale est de comprendre pourquoi vous êtes autorisé à affecter une méthode ou lambda à un délégué compatible. Comme indiqué ci-dessus, cela fait partie du support du langage C # pour les délégués.
Alors enfin pour répondre à votre question:
Lorsque vous utilisez, Invoke()
vous attribuez un appel METHOD au délégué en utilisant le traitement spécial du langage C # pour affecter des méthodes ou des lambdas à un délégué plutôt que d'essayer d'attribuer un type incompatible - par conséquent, il compile OK.
Pour être tout à fait clair, le code qui se compile dans votre OP:
public test Success()
{
Func<int, int> f = x => x;
return f.Invoke; // <- code successfully compiled
}
Est en fait converti conceptuellement en quelque chose comme:
public test Success()
{
Func<int, int> f = x => x;
return new test(f.Invoke);
}
Alors que le code défaillant tente d'affecter entre deux types incompatibles:
public test Fail()
{
Func<int, int> f = x => x;
return f; // Attempting to assign one delegate type to another: Fails
}