2012-04-16 3 views
12

Я бы ожидать, что следующие три строки кода, чтобы быть таким же:используя сливающиеся нулевой оператор на обнуляемых типов изменений неявный тип

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; 

Так что я думаю, мой вопрос, почему неявный тип изменяется, когда я использую ??, а также где в документации, которую я мог найти информацию по этому вопросу.

BTW, это не сценарий реального мира, но я хотел бы знать, почему использование ?? изменяет (неявный) тип.

+3

Почему вы ожидаете 'nullableDateTime ?? DateTime.Now' для создания «DateTime?», Когда у компилятора есть достаточная информация, чтобы знать, что результат никогда не будет «null»? –

+0

@Damien: в моем первом и втором примере компилятор также имеет достаточную информацию, чтобы знать, что результат никогда не будет «null». Именно по этой причине я нахожу это поведение странным. – comecme

+1

Но '?: 'поддерживает гораздо больший диапазон возможных входов (нет причин, по которым« условие »должно быть связано с любым результатом« выражение »вообще). Таким образом, для компилятора было бы необычным, чтобы выполнить этот анализ против '?:'. Принимая во внимание, что для '??', он точно знает, что результатом будет первое выражение без возможности того, чтобы это выражение было нулевым, или второе выражение. –

ответ

6

Ваши первые два примера приводят вас в заблуждение; Лучше всего было бы рассматривать не вашему

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime 
    : DateTime.Now; 

а

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime.Value 
    : DateTime.Now; 

процитировать раздел 7.12 "Нулевая оператор коалесцирующей" из спецификации C# 3.0 (извинения за немного Каболки форматирования):

Тип выражения a ?? b зависит от того, какие неявные конверсии являются avai между типами операндов.Для того предпочтения, тип a ?? b является A0, A или B, , где A является тип a, B является тип b (при условии, что b имеет тип), и A0 является базовым типом A, если A является нулевым типом, или A в противном случае.

Так что если a является Nullable<Something> и b может быть неявно преобразован в Something, тип всего выражения будет Something. Как предлагает @Damien_The_Unbeliever, точка этого оператора - объединить нули!

+1

До сих пор я искал только документацию MSDN по адресу '??'] (http://msdn.microsoft.com/en-us/library/ms173224.aspx) и [Использование нулевых типов] (http: // msdn .microsoft.com/EN-US/библиотека/2cf62fcy.aspx). Они никогда не используют 'var' в этих примерах, но назначают явный тип. Во всяком случае, по-видимому, 'a ?? b' is ** not ** точно так же, как 'a! = null? a: b', когда дело доходит до типов с нулевым значением. – comecme

5

Перейти на весь язык адвоката, на мгновение. Из C# спецификации (версия 4):

7,13

Тип выражения a ?? b зависит от того, неявные преобразования доступны на операндов. В порядке предпочтения, тип a ?? b является A0, A или B, где A является типом a (при условии, что a имеет тип), B является типом b (при условии, что b имеет тип), и A0 является базовым типом A, если A является нулевым типом, или A в противном случае.

Таким образом, ?? явно определен, чтобы предпочесть базовый тип первого выражения, если это первое выражение является типом с нулевым значением.

В то время как язык из 7.14 (касающиеся ?:) обсуждаются только фактические типы x и y, от формы b ? x : y, и обсуждает неявные преобразования между этими двумя типами.

Если неявное преобразование (§6.1) существует с X на Y, но не от Y к X, то Y является тип условного выражения

Поскольку Nullable(T) определяет неявное преобразование от T до Nullable(T), и только явный конверсия от Nullable(T) до T, единственный возможный тип общего выражения - Nullable(T).

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