2014-02-14 2 views
52

После выражения нормальнотроичной поведение оператора несогласованность

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

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

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

Не удается неявно преобразовать тип «Int» на «короткие». Явное преобразование существует (вы пропускаете листинг?)

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

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

Буду Вам признателен, если вы могли бы помочь мне.

+5

из [тега: тройной-оператор]: «Тройной оператор ** ** любого оператора, который принимает три аргумента для тройного условного оператора' '...':.? ', Используйте' тег : условный оператор' »(Мой акцент) –

+2

Очень интересный вопрос ... – Laoujin

+2

индивидуальный вопрос для [Eric Lippert] (http://stackoverflow.com/users/88656/eric-lippert) – Habib

ответ

60

C# language specification, version 5, раздел 6.1.9:

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

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

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

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

  • литералов (включая нуль буквального).

[...]

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

Это правильный ответ, +1 – ken2k

+0

Пятно на. Какой ответ мы должны увидеть больше на SO! – Baldrick

+0

Я могу казаться строгим, но строковые литералы не должны рассматриваться как постоянные выражения. Почему «System.String» особенный? –

4

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

+5

Это очевидно, и это не объясняет ошибку –

+0

@SergeyBerezovskiy Наоборот? Это объясняет, почему в первом случае нет ошибки, хотя, очевидно, это должна быть ошибка компиляции. –

+1

@Joker_vD Нет, это объясняет, почему в первом случае нет ошибок, и почему их не должно быть. – hvd

18

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

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 
+0

Нам нужно доказать :) Возможно, какой-то IL-код? –

+0

1 не следует рассматривать как короткий, но как int, если вы явно не набросаете его. – ken2k

+0

Мое доказательство является недопустимым кодом, отмеченным R # в первом случае ('2' недостижимо) –

Смежные вопросы