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) .
上一篇: 了解空合并运算符(??)
