95 votes

Roslyn a échoué compiler le code

Après que j’ai migré mon projet de VS2013 à VS2015 n’est plus le projet est généré. Une erreur de compilation se produit dans l’instruction LINQ suivante :

Le compilateur retourne une erreur :

D’erreur CS0165 utilisation de variable locale non assignée « b »

Ce qui provoque ce problème ? Est il possible de le fixer par un compilateur réglage ?

112voto

Jon Skeet Points 692016

Quelle est l'origine de ce problème?

Ressemble à un compilateur de bug pour moi. Bien que l' decimal.TryParse(v, out a) et decimal.TryParse(v, out b) expressions sont évaluées de façon dynamique, je voudrais attendre le compilateur pour comprendre encore que par le temps qu'il atteigne a <= b, les deux a et b sont définitivement attribué. Même avec la weirdnesses vous pouvez venir avec dans le typage dynamique, je m'attends à ne jamais évaluer a <= b après l'évaluation de l' TryParse des appels.

(Typage dynamique rend les choses plus confuses, mais il s'avère que j'ai eu tort dans cette partie - c'est tout à fait possible d'avoir une expression A && B && C qui évalue A et C mais pas B - si vous êtes assez rusé. Voir la Roslyn rapport de bug pour Neal Gafter ingénieux exemple.)

Est-il possible d'y remédier grâce à des paramètres du compilateur?

Non, mais il existe des solutions de contournement.

Tout d'abord, vous pourriez arrêter d'être dynamique - si vous savez que vous ne pourrez jamais utiliser des chaînes, vous pouvez utiliser IEnumerable<string> ou donner de la gamme variable v d'un type d' string (c - from string v in array). Que serait mon option préférée.

Si vous avez vraiment besoin de garder une dynamique, donne - b variable pour commencer:

decimal a, b = 0m;

Vous ne devriez pas, mais il ne pourra pas faire de mal.

En outre, il semble que l'ajout de parenthèses marche aussi:

where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)

Je n'ai aucune idée pourquoi cela devrait aider... mais maintenant compile pour moi, au moins... et ne devrait pas affecter la sortie, aussi loin que je peux voir.

21voto

JaredPar Points 333733

Cela ne semble pas y avoir un bug, ou du moins une régression, dans le compilateur de Roslyn. Le bug suivant a été déposé pour le suivre :

https://github.com/dotnet/Roslyn/issues/4509

Dans l’intervalle, de Jon excellente réponse a un couple de solutions de contournement.

16voto

Rawling Points 21932

Depuis que je suis instruit si dur dans le rapport de bug, je vais essayer de vous l'expliquer moi-même.


Imaginez T est un certain type défini par l'utilisateur avec un cast implicite d' bool qui alterne entre false et true, en commençant par false. Aussi loin que le compilateur sait, l' dynamic premier argument pour le premier && peut évaluer à ce type, de sorte qu'il a d'être pessimiste.

Si, ensuite, il laissait le code de la compilation, ce qui peut se produire:

  • Lorsque la dynamique liant évalue la première &&, il effectue les opérations suivantes:
    • Évaluer le premier argument
    • C'est un T - implicitement la convertir en bool.
    • Oh, c'est false, de sorte que nous n'avons pas besoin d'évaluer le deuxième argument.
    • Rendre le résultat de l' && évaluer en tant que premier argument. (Non, pas false, pour une raison quelconque.)
  • Lorsque la dynamique liant évalue le deuxième &&, il effectue les opérations suivantes:
    • Évaluer le premier argument.
    • C'est un T - implicitement la convertir en bool.
    • Oh, c'est true, afin d'évaluer le deuxième argument.
    • ... Oh merde, b n'est pas affecté.

Dans spec termes, en bref, il existe des "définitive" d'assignation des règles qui nous permettent de dire si une variable est "certainement affecté" ou "certainement pas attribué", mais aussi si elle est "définitivement attribuée après l' false déclaration" ou "certainement attribuée après l' true déclaration".

Il en existe un, de sorte que lorsque vous traitez avec des && et || (et ! et ?? et ?:), le compilateur peut examiner si les variables peuvent être affectés, en particulier les branches d'un complexe expression booléenne.

Cependant, ces travaux seulement tandis que les expressions " types restent booléenne. Lors de la partie de l'expression est - dynamic (ou un non-booléenne de type statique) on ne peut plus fiable de dire que l'expression est - true ou false - la prochaine fois que nous convertir en bool afin de décider quelle direction prendre, il peut avoir changé son esprit.

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