Почему это не компилируется?
int? number = true ? 5 : null;
Тип условного выражения не может быть определен, поскольку не существует неявного преобразования между int и <null>
Почему это не компилируется?
int? number = true ? 5 : null;
Тип условного выражения не может быть определен, поскольку не существует неявного преобразования между int и <null>
Ответы:
Спецификация (§7.14) гласит, что для условного выражения b ? x : y
существует три возможности, x
и y
оба имеют тип и выполняются определенные хорошие условия , только один из x
и y
имеет тип, и определенные хорошие условия выполняются, или ошибка времени компиляции происходит. Здесь «определенные хорошие условия» означают, что возможны определенные преобразования, о которых мы поговорим ниже.
Теперь давайте обратимся к немецкой части спецификации:
Если только один из
x
иy
имеет тип, и оба,x
иy
неявно преобразуются в этот тип, то это тип условного выражения.
Проблема здесь в том, что в
int? number = true ? 5 : null;
только один из условных результатов имеет тип. Вот x
это int
буквально, и y
это null
который не не имеют типа и null
не неявно раскладывается в int
1 . Следовательно, «определенные хорошие условия» не выполняются, и возникает ошибка времени компиляции.
Там являются два пути вокруг этого:
int? number = true ? (int?)5 : null;
Здесь мы все еще в случае, когда только один из x
и y
имеет тип. Обратите внимание , что до null
сих пор не имеет типа пока компилятор не будет иметь никаких проблем с этим , потому что (int?)5
и null
оба неявно преобразованы в int?
(§6.1.4 и §6.1.5).
Другой способ, очевидно,
int? number = true ? 5 : (int?)null;
но теперь мы должны прочитать другой пункт в спецификации, чтобы понять, почему это нормально:
Если
x
имеет типX
иy
имеет тип,Y
то
Если неявное преобразование (§6.1) существует из
X
toY
, но не изY
toX
, тогдаY
это тип условного выражения.Если неявное преобразование (§6.1) существует из
Y
toX
, но не изX
toY
, тогдаX
это тип условного выражения.В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.
Вот x
типа int
и y
типа int?
. Там нет неявного преобразования int?
к int
, но есть неявное преобразование int
к int?
такому типу выражения int?
.
1 : Отметим далее, что тип левой части игнорируется при определении типа условного выражения, что является распространенным источником путаницы.
new int?()
на месте (int?)null
.
DateTime
, когда это потребуется,(DateTime?)
null
не имеет идентифицируемого типа - просто нужно немного подтолкнуть его, чтобы сделать его счастливым:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;
и int? number = true ? (int?)5 : null;
как компиляции !! Царапина, царапина
Как уже упоминали другие, 5 является int
, и null
не может быть неявно преобразовано в int
.
Вот другие способы обойти эту проблему:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Кроме того, везде, где вы видите int?
, вы также можете использовать Nullable<int>
.
В C# 9
этом сейчас разрешен блог
Цель набрана ?? и ?
Иногда условно и?: выражения не имеют очевидного общего типа между ветвями. Такие случаи сегодня терпят неудачу, но C # 9.0 разрешит их, если есть целевой тип, в который преобразуются обе ветви:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
Или ваш пример:
// Allowed in C# 9.
int? number = true ? 5 : null;