51 votes

Incohérence du comportement de l'opérateur ternaire

L'expression suivante est ok

 short d = ("obj" == "obj" ) ? 1 : 2;
 

Mais quand vous l'utilisez comme ci-dessous, une erreur de syntaxe se produit

 short d = (DateTime.Now == DateTime.Now) ? 1 : 2;
 

Impossible de convertir implicitement le type 'int' en 'short'. Une conversion explicite existe (manque-t-il un casting?)

Quelqu'un peut-il expliquer pourquoi il en est ainsi?

Existe-t-il une différence entre comparer chaîne à chaîne et date-heure dans un opérateur ternaire, pourquoi?

Je vous serais reconnaissant si vous pouviez m'aider.

59voto

Damien_The_Unbeliever Points 102139

Spécification du langage C#, version 5, l'article 6.1.9:

Implicite de l'expression constante de conversion permet les conversions suivantes:

  • Une constante de l'expression (§7.19) de type int peut-être convertie en type sbyte, byte, short, ushort, uint, ou ulong, à condition que la valeur de la constante-l'expression est dans la plage du type de destination.

Votre premier exemple est une expression constante, car elle peut être évaluée au moment de la compilation. Mais voir la section 7.19 pour plus de détails:

Seules les constructions suivantes sont autorisées dans des expressions constantes:

  • Les littéraux (y compris le littéral null).

[...]

  • Les prédéfinis +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, et >= opérateurs binaires, à condition que chaque opérande est d'un type énuméré ci-dessus.
  • L' ?: opérateur conditionnel.

17voto

Jakub Konecki Points 28852

Je crois que dans le premier cas, le compilateur sait que les chaînes sont égales au moment de la compilation et donc optimise le code pour seulement:

short d = 1;

Qui fonctionne parce qu' 1 peut être attribuée à l' short variable.

Dans le second cas, l'optimisation ne peut pas se produire parce que le compilateur ne peut pas déduire de l'égalité au moment de la compilation, il laisse:

short d = (DateTime.Now == DateTime.Now) ? (long)1 : (long)2;

Cela permettra de compiler:

short d = (DateTime.Now == DateTime.Now) ? (short)1 : (short)2;

IL (LinqPad) pour appeler à court d = ("obj" == "obj" ) ? 1 : 2;:

IL_0001:  ldc.i4.1    
IL_0002:  stloc.0     // d

4voto

Ondrej Svejdar Points 5039

"obj" == "obj" peut être résolu au moment de la compilation; le compilateur le traite comme

court d = 1;

 namespace ConsoleApplication1 {
  class Program {
    static void Main(string[] args) {
      short d = ("obj" == "obj") ? 1 : 2;
    }
  }
}

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
 // Code size       4 (0x4)
 .maxstack  1
 .locals init ([0] int16 d)
 IL_0000:  nop
 IL_0001:  ldc.i4.1
 IL_0002:  stloc.0
 IL_0003:  ret
 } // end of method Program::Main
 

DateTime.Now == DateTime.Now ne peut pas être résolu au moment de la compilation et génère une erreur.

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