2013-09-12 2 views
19

Из документации MSDN, следующие два фрагмента равны:условного оператора: с Nullable типа Литейно

bool value; 
int x = (value) ? 0 : 1; 

И

bool value; 
int x; 
if (value) 
    x = 0; 
else 
    x = 1; 

Отлично, замечательно. Я использую это все время. Тесный и эффективный.

Если попробовать это с обнуляемого типа, например, так:

int? x = (value.HasValue) ? value.Value : null; 

Мы получаем ошибку компиляции:

The type of conditional expression cannot be determined 
because there is no implicit conversion between '{NullableType}' and null. 

Это компилируется нормально:

int? value; 
int? x; 

if (value.HasValue) 
    x = value.Value; 
else 
    x = null; 

Так , Я понимаю, что для компиляции первого оператора компилятор требует явного перевода на (int?)null. Я не понимаю, почему это требуется в этом выражении, но не в блоке If Else.

+0

Возможный дубликат: http://stackoverflow.com/questions/295833/nullable-type-issue-with-conditional-operator –

+1

@NickGotch Я видел ваше сообщение, но я честно не удовлетворен ответом. Я хочу понять, почему актеры необходимы при использовании одного типа синтаксиса и другого. – Michael

+1

Я думаю, что в этом случае вы можете просто «x = value», или я ошибаюсь? –

ответ

26

null может представлять любой объект-тип данных. Вам нужно указать null как тип данных, чтобы он знал, о чем вы говорите.

int? x = (value.HasValue) ? value.Value : (int?)null; 

Я знаю, это звучит немного странно.


Чтобы ответить на вопросы в комментариях:

Why is it not implicit though?
Yeah, I get that. But why do I not have to cast it in a If Else block?

Давайте пройдемся по коду.

Ваше else заявление выглядит следующим образом:

else x = null; 

Это означает, что вы присваиваете значение null к x. Это действительно, потому что x - int?, который принимает nulls.

Разница возникает, когда у вас есть тернарный оператор. В нем говорится: «присвойте значение оператора x». Вопрос (и причина вашей ошибки) заключается в том, какой тип данных является результатом тернарного оператора?

Из вашего кода вы не можете быть уверены, и компилятор поднимает руки вверх.

int? x = (value.HasValue) ? value.Value : null; 
// int?  bool    int  ?? 

Что тип данных null? Вы быстро можете сказать «хорошо, что это int?, потому что другая сторона - int, а результат - int?». Проблема заключается в том, что примерно следующее:

string a = null; 
bool? b = null; 
SqlConnectionStringBuilder s = null; 

Это также справедливо, что означает null могут быть использованы для any object-based datatype. Вот почему вы должны явно указать null как тип, который хотите использовать, потому что он может быть использован для чего угодно!


Другое объяснение (и, возможно, более точный):

You can't have an implicit cast between a nullable and a non-nullable value.

int не-обнуляемым (это структура), где null есть. Вот почему в ответе Хабиба вы можете поставить бросок на левую или правую сторону.

+0

Почему это не подразумевается? – Tharwen

+0

Да, я понимаю. Но почему мне не нужно бросать его в блок If Else? – Michael

+0

@Tharwen и Michael, обновлено с дополнительными пояснениями – gunr2171

6
var x = value.HasValue ? value.Value : default(int?); 

также работает.

+0

простой и хитрый. Спасибо приятель. –

11

Для Condtional operator MSDN гласит:

Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.

Так вы случае, если ваш first_expression и second_expression являются:

int? x = (value.HasValue) ? value.Value : null; 
          ^^^^^^^^  ^^^^^ 
          first exp  2nd Exp 

Теперь, если вы видите, ваше первое выражение типа int, а второе выражение null и оба они не одинаковы, и нет никакого неявного преобразования. Так что литье любых из них в `int? решает проблему.

Итак:

int? x = (value.HasValue) ? (int?) value.Value : null; 

Или

int? x = (value.HasValue) ? value.Value : (int?) null; 

отлично.

Теперь почему это не требуется с if-else, потому что здесь задействовано несколько операторов, и это не один оператор, присваивающий значение.

1

В сообщении documentation for the ?: operator указано, что тип выражения b? х: у определяются путь изучения типов х и у:

  • If X and Y are the same type, then this is the type of the conditional expression.
  • Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
  • Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
  • Otherwise, no expression type can be determined, and a compile-time error occurs.

В вашем примере

int? x = (value.HasValue) ? value.Value : null; 

нет неявного преобразования между Int и нулем так применяется последняя пуля.

+0

Я думаю, что это лучший ответ, но почему преобразование использует 'b' для определения типа? – MirroredFate

0

Причина в том, что тип условного выражения определяется вторым и третьим операторами условного оператора (? :).

Поскольку null не имеет типа, компилятор не может определить тип общего выражения, поэтому он испускает ошибку компилятора.

Причина, по которой он работает с простым оператором присваивания (=), состоит в том, что левая часть оператора определяет тип. Поскольку в выражении If тип x уже известен, компилятор не жалуется.

Для получения дополнительных пояснений см. Раздел 7.14 (Условный оператор) и раздел 7.17.1 (Простое назначение).

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