Использование объединяющего нулевого оператора для обнуляемых типов изменяет неявный тип

Я ожидаю, что следующие три строки кода будут одинаковыми:

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 является A0, A, или же B, где A это тип a, B это тип b (при условии, что b имеет тип), и A0 это основной тип 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),

Другие вопросы по тегам