关于c#:在可空类型上使用coalescing null运算符更改隐式类型

using coalescing null operator on nullable types changes implicit type

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

1
2
3
4
5
6
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

实际上,假设在方法的其余部分中,我将使用

1
if (someCondition) dateTimeNullable2 = null;

在我让resharper用空合并版本替换第二个表达式之前,这将编译得很好。

Afaik,更换

1
somevar != null ? somevar : somedefault;

具有

1
somevar ?? somedefault;

确实应该产生相同的结果。但对于可以为空的类型的隐式键入,编译器似乎威胁到??,就好像它的意思一样。

1
somevar != null ? somevar.Value : somedefault;

所以我想我的问题是,当我使用??时,为什么隐式类型会发生变化,而且在文档中我可以在哪里找到关于这个的信息。

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


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

1
2
3
var dateTimeNullable1 = nullableDateTime.HasValue
    ? nullableDateTime
    : DateTime.Now;

而是

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

引用C 3.0规范的第7.12节"空合并运算符"(对稍微不正确的格式表示歉意):

The type of the expression a ?? b depends on which implicit
conversions are available between the types of the operands. In order
of preference, the type of a ?? b is A0, A, or B,
where A is the type of a, B is the type of b (provided that
b has a type), and A0 is the underlying type of A if
A is a nullable type, or A otherwise.

因此,如果aNullable,而b可以隐式转换为Something,那么整个表达式的类型将是Something。正如@damien_the_unbeliever所建议的,这个操作符的要点是合并nulls!


去做语言律师,一会儿。根据C规范(第4版):

7.13

The type of the expression a ?? b depends on which implicit conversions are available on the operands. In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a (provided that a has a type), B is the type of b (provided that b has a type), and A0 is the underlying type of A if A is a nullable type, or A otherwise.

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

而7.14的语言(处理?:)只从b ? x : y的形式讨论xy的实际类型,并讨论这两种类型之间的隐式转换。

If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression

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