Donc, pour commencer, la première expression ne peut peut-être appeler la première surcharge. Ce n'est pas une expression valide pour un Func<Task>
car il y a un chemin de code qui renvoie une valeur non valide (void
au lieu de Task
).
() => while(true)
est en fait une méthode valable pour la signature. (Elle, avec des implémentations telles que l' () => throw new Expression();
sont valables corps des méthodes qui renvoient tout type, y compris void
, un point intéressant de l'anecdote, et pourquoi auto méthodes générées à partir d'un IDE généralement tout juste de lancer une exception, il va compiler indépendamment de la signature de la méthode.) Une méthode qui boucle à l'infini est une méthode dans laquelle il n'y a pas de code chemins qui ne renvoie pas la valeur correcte (et c'est vrai que la "bonne valeur" void
, Task
, ou littéralement n'importe quoi d'autre). C'est évidemment parce qu'il jamais renvoie une valeur, et il le fait en sorte que le compilateur peut le prouver. (Si il l'a fait en sorte que le compilateur ne pouvais pas le prouver, comme elle n'a pas résolu le problème de l'arrêt, après tout, alors nous serions dans le même bateau que l' A
.)
Donc, pour notre boucle infinie, ce qui est mieux, étant donné que tant de surcharge sont applicables. Ceci nous amène à notre betterness section de C# specs.
Si nous allons à l'article 7.4.3.3, point 4, nous voyons:
Si E est une fonction anonyme, T1 et T2 sont des types délégués ou de l'expression des types d'arbres à l'identique des listes de paramètres, et en déduit le type de retour de X existe pour E dans le contexte de la liste des paramètres (§7.4.2.11):
[...]
si T1 a un type de retour Y, et T2 est nulle retour, alors C1 est le meilleur taux de conversion.
Donc, lors de la conversion d'un délégué anonyme, qui est ce que nous faisons, il préfère la conversion qui retourne une valeur de plus d'un c'est - void
, de sorte qu'il choisit Func<Task>
.