2016-01-12 2 views
0

je lutte avec le démontage du CIL du paramètre à l'WriteLine() appel à:démontage CIL d'un paramètre de fonction impliquant une expression ternaire

FileInfo path = new FileInfo(@"c:\a.txt"); 
Console.WriteLine("prefix: " + path != null ? path.FullName : "null"); 

CIL dissasembly

.locals init (
    [0] class [mscorlib]System.IO.FileInfo path 
) 

// ... 

IL_000c: ldstr "prefix: " 
IL_0011: ldloc.0 
IL_0012: call string [mscorlib]System.String::Concat(object, object) 
IL_0017: brtrue.s IL_0020 

IL_0019: ldstr "null" 
IL_001e: br.s IL_0026 

IL_0020: ldloc.0 
IL_0021: callvirt instance string [mscorlib]System.IO.FileSystemInfo::get_FullName() 

IL_0026: call void [mscorlib]System.Console::WriteLine(string) 

Il me semble que Concat est appelée en premier, et alors seulement l'opérateur ternaire est évalué. En particulier:

IL_0012Concat("prefix", path) semble être appelé,
IL_0012brtrue.s IL_0020 // branche basée sur le précédent retour valeur

  • Pourquoi Concat appelé avec path comme paramètre au lieu de path.FullName?
  • Est-ce que Concat renvoie null, si son premier paramètre est null? Comment le compilateur le sait-il? (Si je remplace + avec mon propre , le démontage à quelque chose que je préférerais attendre.)

Pourriez-vous s'il vous plaît expliquer, comment le démontage gère le paramètre ternaire et l'appel à WriteLine?

Répondre

8

Ce n'est pas un problème de démontage, c'est un problème de priorité des opérateurs.

Votre expression est évaluée comme

("prefix: " + path != null) ? path : "null"; 

Pas aussi

"prefix: " + (path != null ? path : "null"); 

que vous semblez attendre. Il suffit d'utiliser correctement entre parenthèses et vous serez très bien :)

En fait, il est un raté « l'optimisation » de la part du compilateur - car string.Concat("prefix: ", whatever) peut jamais être nulle, vous toujours obtenir path.FullName. Bien sûr, un ternaire qui n'évalue que l'une de ses options est presque certainement un bug, donc ...