35 votes

Résolution particulière de surcharge avec while (vrai)

J'ai été mise en œuvre sync/async surcharges quand je suis tombé sur cette étrange situation:

Quand j'ai régulièrement une expression lambda sans paramètre ou une valeur de retour, il va à l' Run de surcharge avec l' Action paramètre, ce qui est prévisible. Mais lorsque que lambda a un while (true) il va à la surcharge de la Func paramètre.

public void Test()
{
    Run(() => { var name = "bar"; });
    Run(() => { while (true) ; });
}

void Run(Action action)
{
    Console.WriteLine("action");
}

void Run(Func<Task> func) // Same behavior with Func<T> of any type. 
{
    Console.WriteLine("func");
}

Sortie:

action
func

Alors, comment peut-il être? Est-il une raison pour cela?

26voto

Servy Points 93720

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>.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X