在可空类型上使用coalescing null运算符更改隐式类型

我希望接下来的三行代码是相同的:

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?DateTime

事实上,让我们说在方法的其余部分,我会使用

 if (someCondition) dateTimeNullable2 = null; 

这将编译得很好,直到我让ReSharper用空合并版本替换第二个表达式。

AFAIK,取代

 somevar != null ? somevar : somedefault; 

 somevar ?? somedefault; 

应该确实产生相同的结果。 但对于可空类型的隐式类型,编译器似乎有威胁?? 好像这意味着。

 somevar != null ? somevar.Value : somedefault; 

所以我想我的问题是为什么隐藏类型在我使用时会改变?? ,以及在文档中我可以找到关于此的信息。

顺便说一下,这不是一个现实世界的场景,但我想知道为什么使用?? 更改(隐式)类型。

你的前两个例子让你误入歧途; 更好的是不要考虑你的

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

反而

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

引用C#3.0规范的第7.12节“空合并运算符”(略微粗略格式化的道歉):

表达式的类型a ?? b a ?? b取决于操作数类型之间可用的隐式转换。 按优先顺序排列,类型为a ?? b a ?? bA 0AB ,其中A是a的类型, Bb的类型(假设b具有类型),如果A是可空类型,则A 0A的基础类型,或者否则。

因此,如果aNullable ,并且b可以隐式转换为Something ,则整个表达式的类型将为Something 。 正如@Damien_The_Unbeliever建议的那样,这个运算符的意思是合并空值!

一时间去找所有的语言律师。 从C#规范(版本4):

7.13

表达式的类型a ?? b a ?? b取决于操作数上可用的隐式转换。 按优先顺序排列,类型为a ?? b a ?? bA0AB ,其中A是a的类型(假设a具有类型), Bb的类型(假设b具有类型),并且A0A的基础类型,如果A是可以为空的类型,否则为A

那么, ?? 如果第一个表达式是可空类型,则显式定义为首选表达式的基础类型。

7.14中的语言(处理?: :)只讨论了forms为b ? x : yxy的实际类型b ? x : y b ? x : y ,并讨论这两种类型之间的隐式转换。

如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型

由于Nullable(T)定义了从TNullable(T)隐式转换,并且只有从Nullable(T)T显式转换,因此整个表达式中唯一可能的类型是Nullable(T)