Je ne comprends pas ce cas:
public delegate int test(int i);
public test Success()
{
Func<int, int> f = x => x;
return f.Invoke; // <- code successfully compiled
}
public test Fail()
{
Func<int, int> f = x => x;
return f; // <- code doesn't compile
}
Pourquoi la compilation est-elle OK lorsque j'utilise la Invoke
méthode et pas OK lorsque je reviens csharp Func<int,int>
directement?
delegate void test1(int i);
etdelegate void test2(int i);
Réponses:
Il y a deux choses que vous devez savoir pour comprendre ce comportement.
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.É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é:
Alors:
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:
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
ettest2
car ce sont des types différents.Si cela aide à y penser, considérez cette hiérarchie de classes:
Le code suivant ne compile pas, même si
Test1
etTest2
tirer de la même classe de base: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:
Est en fait converti conceptuellement en quelque chose comme:
Alors que le code défaillant tente d'affecter entre deux types incompatibles:
la source
Dans le second cas,
f
est de typeFunc<int, int>
, mais la méthode est censée retourner atest
. Ce sont des types non liés (délégués), qui ne sont pas convertibles entre eux, donc une erreur de compilation se produit. Vous pouvez accéder à cette section de la spécification de langue et rechercher «déléguer». Vous ne trouverez aucune mention des conversions entre les délégués qui ont les mêmes signatures.Dans le premier cas cependant, il
f.Invoke
s'agit d'une expression de groupe de méthodes , qui n'a en fait pas de type. Le compilateur C # convertira les expressions de groupe de méthodes en types de délégués spécifiques en fonction du contexte, via une conversion de groupe de méthodes .(Citant la 5ème puce ici , c'est moi qui souligne)
Dans ce cas, il est converti en
test
type délégué.En d'autres termes,
return f
cela ne fonctionne pas car af
déjà un type, maisf.Invoke
n'a pas encore de type.la source
Le problème ici est la compatibilité de type:
Voici la définition du délégué Func des sources MSDN:
public delegate TResult Func<in T, out TResult>(T arg);
Si vous voyez qu'il n'y a pas de relation directe entre le Func mentionné ci-dessus et votre délégué défini:
public delegate int test(int i);
Les délégués sont comparés à l'aide de la signature, qui est les paramètres d'entrée et le résultat de sortie, finalement un délégué est un pointeur de fonction et deux fonctions peuvent être comparées uniquement via la signature. Au moment de l'exécution, la méthode invoquée via Func est attribuée au
Test
délégué, puisque Signature est la même, elle fonctionne de manière transparente. Il s'agit d'une affectation de pointeur de fonction, où leTest
délégué invoquera désormais la méthode pointée par le délégué FuncEntre Func et délégué de test, il n'y a pas de compatibilité de type / affectation, Func ne peut pas remplir dans le cadre des règles système Type. Même lorsque son résultat peut être attribué et renseigné
test delegate
comme dans le premier cas.la source