Consider the following code:
bool x;
bool? y = null;
x = y?? true;
Assigning a bool?
to a bool
is a compile-time error, but the above code succeeds both at compile and run-time. Why? Although the 3rd statement ensures we never assign null
to x
, in case y
is not null, we're still assigning a bool?
to a bool
, so it should be an error from compiler's POV, no?
Or is it that C# compiler is smart enough to find out that a particular piece of code cannot possibly create a situation where a null
would be assigned to x
?
The type of this expression:
y ?? true
is bool
, not bool?
.
From section 7.13 of the C# 5 spec:
The type of the expression
a ?? b
depends on which implicit conversions are available on the operands. In order of preference, the type ofa ?? 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. Specifically,a ?? b
is processed as follows:
- If A exists and is not a nullable type or a reference type, a compile-time error occurs.
- If
b
is a dynamic expression, the result type is dynamic. At run-time,a
is first evaluated. Ifa
is not null,a
is converted to dynamic, and this becomes the result. Otherwise,b
is evaluated, and this becomes the result.- Otherwise, if A exists and is a nullable type and an implicit conversion exists from
b
to A0, the result type is A0. At run-time,a
is first evaluated. Ifa
is not null,a
is unwrapped to type A0, and this becomes the result. Otherwise,b
is evaluated and converted to type A0, and this becomes the result.- Otherwise, if A exists and an implicit conversion exists from
b
to A, the result type is A. At run-time,a
is first evaluated. Ifa
is not null,a
becomes the result. Otherwise,b
is evaluated and converted to type A, and this becomes the result.- Otherwise, if
b
has a type B and an implicit conversion exists from a to B, the result type is B. At run-time,a
is first evaluated. Ifa
is not null,a
is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise,b
is evaluated and becomes the result.- Otherwise,
a
andb
are incompatible, and a compile-time error occurs.
In your case, we're in the third bullet:
bool?
bool
bool
... so the result type is bool
, and you can assign that to a variable of type bool
.
See more on this question at Stackoverflow