Использование объединяющего нулевого оператора для обнуляемых типов изменяет неявный тип
Я ожидаю, что следующие три строки кода будут одинаковыми:
public static void TestVarCoalescing(DateTime? nullableDateTime)
{
var dateTimeNullable1 = nullableDateTime.HasValue ? nullableDateTime : DateTime.Now;
var dateTimeNullable2 = nullableDateTime != null ? nullableDateTime : DateTime.Now;
var dateTimeWhatType = nullableDateTime ?? DateTime.Now;
}
Во всех случаях я назначаю nullableDateTime
к новой переменной. Я ожидаю, что тип всех переменных станет DateTime?
так как это тип nullableDateTime
, Но, к моему удивлению, тип dateTimeWhatType
просто становится DateTime
так что не обнуляется.
Что еще хуже, ReSharper предлагает заменить второе выражение на объединяющее выражение, превращающее его в выражение 3. Поэтому, если я позволю ReSharper делать свое дело, тип переменной изменится с DateTime?
в DateTime
,
На самом деле, скажем, что в оставшейся части метода я бы использовал
if (someCondition) dateTimeNullable2 = null;
Это скомпилировалось бы отлично, пока я не позволю ReSharper заменить второе выражение пустой версией.
AFAIK, замена
somevar != null ? somevar : somedefault;
с
somevar ?? somedefault;
должен действительно дать тот же результат. Но для неявной типизации на обнуляемый тип, компилятор кажется угрозой ??
как будто это значит.
somevar != null ? somevar.Value : somedefault;
Поэтому я предполагаю, что мой вопрос заключается в том, почему неявный тип изменяется, когда я использую ??
, а также где в документации я мог найти информацию об этом.
Кстати, это не сценарий реального мира, но я хотел бы знать, почему использование ??
изменяет (неявный) тип.
2 ответа
Ваши первые два примера вводят вас в заблуждение; лучше было бы рассмотреть не ваш
var dateTimeNullable1 = nullableDateTime.HasValue
? nullableDateTime
: DateTime.Now;
скорее
var dateTimeNullable1 = nullableDateTime.HasValue
? nullableDateTime.Value
: DateTime.Now;
Процитируем раздел 7.12 "Нулевой оператор объединения" спецификации C# 3.0 (извиняюсь за слегка вялое форматирование):
Тип выражения
a ?? b
зависит от того, какие неявные преобразования доступны между типами операндов. В порядке предпочтения типa ?? b
являетсяA
0
,A
, или жеB
, гдеA
это типa
,B
это типb
(при условии, чтоb
имеет тип), иA
0
это основной типA
еслиA
обнуляемый тип, илиA
иначе.
Так что если a
является Nullable<Something>
, а также b
может быть неявно преобразовано в Something
тип всего выражения будет Something
, Как говорит @Damien_The_Unbeliever, цель этого оператора - объединить нули!
Чтобы перейти на все языки адвоката, на мгновение. Из спецификации C# (версия 4):
7,13
Тип выражения
a ?? b
зависит от того, какие неявные преобразования доступны для операндов. В порядке предпочтения типa ?? b
являетсяA0
,A
, или жеB
, гдеA
это типa
(при условии, чтоa
имеет тип),B
это типb
(при условии, чтоb
имеет тип), иA0
это основной типA
еслиA
обнуляемый тип, илиA
иначе.
Так, ??
явно определено для предпочтения базового типа первого выражения, если это первое выражение имеет тип NULL.
В то время как язык из 7.14 (имеет дело с ?:
) обсуждаются только актуальные типы x
а также y
из формы b ? x : y
и обсуждает неявные преобразования между этими двумя типами.
Если неявное преобразование (§6.1) существует из X в Y, но не из Y в X, тогда Y является типом условного выражения
поскольку Nullable(T)
определяет неявное преобразование из T
в Nullable(T)
и только явное преобразование из Nullable(T)
в T
, единственный возможный тип общего выражения Nullable(T)
,