Условный оператор не может бросить неявно?

Я немного озадачен этой небольшой причудой C#:

Учитывая переменные:

Boolean aBoolValue;
Byte aByteValue;

Следующие компиляции:

if (aBoolValue) 
    aByteValue = 1; 
else 
    aByteValue = 0;

Но это не будет:

aByteValue = aBoolValue ? 1 : 0;

Ошибка говорит: "Не может неявно преобразовать тип 'интервал' в 'байт'".

И конечно, это чудовище скомпилирует:

aByteValue = aBoolValue ? (byte)1 : (byte)0;

Что продолжается здесь?

Править:

Использование VS2008, C# 3.5

61
задан MPelletier 7 February 2010 в 14:09
поделиться

3 ответа

Это довольно часто задаваемый вопрос.

В C # мы почти всегда рассуждаем изнутри наружу. Когда вы видите

x = y;

, мы выясняем, что такое тип x, каков тип y и является ли тип y совместимым по присваиванию с x. Но мы не используем тот факт, что мы знаем, что это за тип x, когда мы разрабатываем тип y.

Это потому, что может быть более одного x:

void M(int x) { }
void M(string x) { }
...
M(y); // y is assigned to either int x or string x depending on the type of y

Нам нужно , чтобы иметь возможность определить тип выражения , не зная, чему оно присваивается. Информация о типе передается из выражения, а не в выражение.

Чтобы определить тип условного выражения, мы определяем тип следствия и альтернативные выражения, выбираем более общий из двух типов, который становится типом условного выражения. Итак, в вашем примере тип условного выражения - «int», и он не является константой (если только выражение условия не является константой true или константой false). Поскольку это не константа, вы не можете присвоить его байту; компилятор исходит исключительно из типов, а не из значений, когда результат не является константой.

Исключением из всех этих правил являются лямбда-выражения, где информация о типе действительно перетекает из контекста в лямбда. Разобраться в этой логике было очень сложно.

69
ответ дан 24 November 2019 в 17:21
поделиться

Возможно, у меня нет для вас отличного ответа, но если вы сделаете это во многих местах, вы можете объявить:

private static readonly Byte valueZero = (byte)0;
private static readonly Byte valueOne = (byte)1;

и только эти переменные. Вы можете обойтись без использования const , если он является локальным для проекта.

РЕДАКТИРОВАТЬ: использование только для чтения не имело бы смысла - они никогда не должны изменяться.

7
ответ дан 24 November 2019 в 17:21
поделиться

Я использую VS 2005, и я могу воспроизвести его для логических и логических значений, но не для истинных значений

 bool abool = true;
 Boolean aboolean = true;
 Byte by1 = (abool ? 1 : 2);    //Cannot implicitly convert type 'int' to 'byte'
 Byte by2 = (aboolean ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte'
 Byte by3 = (true ? 1 : 2);     //Warning: unreachable code ;)

Самый простой способ обхода этой проблемы - это cast

 Byte by1 = (Byte)(aboolean ? 1 : 2);

Итак, да, похоже, что тернарный оператор заставляет константы «фиксировать» свои типы как целые числа и отключать неявное преобразование типов, которое в противном случае вы бы получили от констант, которые вписываются в меньший тип.

12
ответ дан 24 November 2019 в 17:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: