вернуть ulong в inline-if

Есть ли причина, по которой я не могу использовать следующий код?

ulong test(int a, int b)
{
    return a == b ? 0 : 1;
}

Он показывает мне:

Cannot implicitly convert type 'int' to 'ulong'. An explicit conversion exists (are you missing a cast?)

Будет работать следующее:

ulong test(int a, int b)
{
    return false ? 0 : 1;
}

Я знаю, как решить проблему. Я просто хочу знать причину.

Спасибо.


person Marcel Niehüsener    schedule 30.09.2015    source источник
comment
В последнем блоке кода сработает ли замена false на true? Может быть, есть какая-то причина, по которой 1 может быть неявно преобразовано 0 не может?   -  person Dan Forbes    schedule 30.09.2015
comment
Уже проверено, разницы нет.   -  person Marcel Niehüsener    schedule 30.09.2015
comment
Это false ? 0 : 1 является константным выражением. Это return a == b ? 0 : 1 нет. Константное выражение типа int можно неявно преобразовать в ulong, если оно соответствует диапазону ulong.   -  person user4003407    schedule 30.09.2015
comment
Я думаю, причина в том, что компилятор оценивает выражение, поэтому для второго нет ошибки. он будет скомпилирован как return 1   -  person M.kazem Akhgary    schedule 30.09.2015
comment
Я просто хочу знать причину. Потому что это добавило бы сложности компилятору без уважительной причины.   -  person Roger Lipscombe    schedule 30.09.2015


Ответы (3)


Давайте посмотрим на получившийся IL-код второго метода:

IL_0000:  nop
IL_0001:  ldc.i4.1
IL_0002:  conv.i8
IL_0003:  stloc.0
IL_0004:  br.s       IL_0006
IL_0006:  ldloc.0
IL_0007:  ret

В IL_0001 литерал 1 помещается в стек (поэтому выражение return false ? 0 : 1; оценивается во время компиляции и внедряется в IL как константа), а в IL_0002 этот литерал преобразуется в Int64.

Из MSDN:

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

Поскольку 1 находится в диапазоне типа данных ulong, такое преобразование всегда будет успешным. Компилятор знает об этом и поэтому выполняет неявное преобразование.

person Kapol    schedule 30.09.2015

Переменные типа int не могут быть неявно преобразованы в ulong, потому что int может представлять отрицательное значение, а ulong — нет. Константа может быть преобразована неявно при условии, что значение константного выражения неотрицательно.

Ваш второй пример - постоянное выражение.

person phoog    schedule 30.09.2015

Это будет работать:

ulong test(int a, int b)
{
    return a == b ? 0UL : 1UL;
}

Видите ли, компилятор определяет тип по размеру числа, поэтому, если вам нужен конкретный тип, вы должны указать суффикс. См. раздел «Литералы» на этой странице MSDN.

Изменить: как мне было указано, этот вопрос не искал ответа о том, как заставить его работать. Я считаю, что в связанной статье MSDN все еще есть некоторая ценность. Он предоставляет информацию, которая может объяснить, почему неудачный случай не работает, но не объясняет, почему другой случай проходит успешно. Действительно интересная проблема.

person David Watts    schedule 30.09.2015
comment
Вопрос не в том, как заставить его работать, а в том, почему второй случай работает, а первый нет. - person juharr; 30.09.2015
comment
@juharr Так оно и есть. Подхожу к концу дня, а тут мой мозг поджаривается. Хотя литеральная часть все еще применяется, верно? Это объясняет, почему это не работает, но не объясняет, почему работает второй случай. - person David Watts; 30.09.2015