14

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

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. 但令我惊讶的是,dateTimeWhatTypejust 的类型变成了DateTime,所以不能为空。

更糟糕的是,ReSharper 建议用空合并表达式替换第二个语句,将其转换为表达式 3。因此,如果我让 ReSharper 做它的事情,变量的类型将从DateTime?变为DateTime

事实上,假设在该方法的其余部分,我会使用

if (someCondition) dateTimeNullable2 = null;

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

AFAIK,替换

somevar != null ? somevar : somedefault;

somevar ?? somedefault;

确实应该产生相同的结果。但是对于可空类型的隐式类型,编译器似乎威胁??到了它的意思。

somevar != null ? somevar.Value : somedefault;

所以我想我的问题是为什么在我使用时隐式类型会发生变化??,以及在文档中我可以找到有关此信息的位置。

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

4

2 回答 2

9

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

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

反而

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

引用 C# 3.0 规范的第 7.12 节“空合并运算符”(对于稍微粗略的格式表示歉意):

表达式的类型a ?? b取决于操作数类型之间可用的隐式转换。按照优先顺序, 的类型a ?? bA0AB,其中A的类型是aB类型b(前提是 b具有类型),并且A0Aif 的基础类型A是可空类型,A否则。

所以如果aisNullable<Something>并且b可以隐式转换为Something,则整个表达式的类型将是Something。正如@Damien_The_Unbeliever 建议的那样,这个运算符的重点是合并空值!

于 2012-04-16T08:26:34.160 回答
5

去所有语言律师,一会儿。从 C# 规范(版本 4):

7.13

表达式的类型a ?? b取决于操作数上可用的隐式转换。按优先顺序, 的类型a ?? bA0AB,其中A的类型是a(前提是a有类型),B是的类型是b(前提是b有类型),并且A0是基础类型AifA是可空类型,或A其他。

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

7.14中的语言(处理)只讨论了and?:的实际类型,来自 form ,并讨论了这两种类型之间的隐式转换。xyb ? x : y

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

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

于 2012-04-16T10:20:46.590 回答