Подтвердить что ты не робот

Несоответствие поведения оператора

Следующее выражение ok

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

Но когда вы используете его, как показано ниже, возникает синтаксическая ошибка.

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

Невозможно неявно преобразовать тип 'int' в 'short'. Явное преобразование существует (вы пропускаете листинг?)

Может кто-нибудь объяснить, почему это так?

Есть ли разница между сопоставлением строк и строк и datetime-to-datetime в тройном операторе, почему?

Буду признателен, если вы поможете мне.

4b9b3361

Ответ 1

Спецификация языка С#, версия 5, раздел 6.1.9:

Неявное преобразование константных выражений допускает следующие преобразования:

  • Константное выражение (§7.19) типа int может быть преобразовано в тип sbyte, byte, short, ushort, uint или ulong при условии, что значение константного выражения находится в пределах диапазона типа назначения.

Ваш первый пример - это константное выражение, потому что его можно оценить во время компиляции. Но см. Раздел 7.19 для более подробной информации:

В константных выражениях допускаются только следующие конструкции:

  • Литералы (включая нулевой литерал).

[...]

  • Предопределенные +, -, *,/,%, <, → , &, |, ^, &, ||, ==,! =, <, > , <; =, и >= двоичные операторы, если каждый операнд имеет тип, указанный выше.
  • Оператор?: условный.

Ответ 2

Я считаю, что в первом случае компилятор знает, что строки равны во время компиляции и поэтому оптимизирует код только:

short d = 1;

Это работает, потому что 1 может быть назначено переменной short.

Во втором случае оптимизация не может произойти, потому что компилятор не может вывести равенство во время компиляции, поэтому он оставляет:

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

Это скомпилирует:

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

IL (LinqPad) для вызова short d = ( "obj" == "obj" )? 1: 2;:

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

Ответ 3

"obj" == "obj" может быть разрешено во время компиляции; компилятор рассматривает его как

short 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 не может быть разрешен во время компиляции и выдает ошибку.