using coalescing null operator on nullable types changes implicit type

I would expect the next three lines of code to be the same:

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;
}

In all cases, I assign nullableDateTime to the new variable. I would expect the type of all variables to become DateTime? since that is the type of nullableDateTime . But to my surprise, the type of dateTimeWhatType just becomes DateTime , so not nullable.

To make things worse, ReSharper suggests to replace the second statement with a null coalescing expression, turning it into expression 3. So if I let ReSharper do its thing, the type of the variable will change from DateTime? to DateTime .

In fact, let's say that in the remainder of the method, I would use

if (someCondition) dateTimeNullable2 = null;

That would compile just fine, until I let ReSharper replace the second expression with the null coalescing version.

AFAIK, replacing

somevar != null ? somevar : somedefault;

with

somevar ?? somedefault;

should indeed produce the same result. But for implicit typing on a nullable type, the compiler seems to threat ?? as if it means.

somevar != null ? somevar.Value : somedefault;

So I guess my question is why the implicit type is changed when I use ?? , and also where in the documentation I could find info on this.

BTW, this isn't a real world scenario, but I would like to know why using ?? changes the (implicit) type.


Your first two examples are leading you astray; better would be to consider not your

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

but rather

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

To quote section 7.12 "The null coalescing operator" of the C# 3.0 spec (apologies for slightly ropey formatting):

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

So if a is Nullable<Something> , and b can be implicitly converted to Something , the type of the whole expression will be Something . As @Damien_The_Unbeliever suggests, the point of this operator is to coalesce nulls!


To go all language lawyer, for a moment. From the C# spec (version 4):

7.13

The type of the expression a ?? b a ?? b depends on which implicit conversions are available on the operands. In order of preference, the type of a ?? b 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.

So, ?? is explicitly defined to prefer the underlying type of the first expression, if that first expression is a nullable type.

Whereas the language from 7.14 (dealing with ?: ) only discusses the actual types of x and y , from the form b ? x : y b ? x : y , and discusses implicit conversions between these two types.

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

Since Nullable(T) defines an implicit conversion from T to Nullable(T) , and only an explicit conversion from Nullable(T) to T , the only possible type of the overall expression is Nullable(T) .

链接地址: http://www.djcxy.com/p/57960.html

上一篇: 了解空合并运算符(??)

下一篇: 在可空类型上使用合并空操作符会改变隐式类型