Несоответствие поведения оператора
Следующее выражение ok
short d = ("obj" == "obj" ) ? 1 : 2;
Но когда вы используете его, как показано ниже, возникает синтаксическая ошибка.
short d = (DateTime.Now == DateTime.Now) ? 1 : 2;
Невозможно неявно преобразовать тип 'int' в 'short'. Явное преобразование существует (вы пропускаете листинг?)
Может кто-нибудь объяснить, почему это так?
Есть ли разница между сопоставлением строк и строк и datetime-to-datetime в тройном операторе, почему?
Буду признателен, если вы поможете мне.
Ответы
Ответ 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 не может быть разрешен во время компиляции и выдает ошибку.