Question

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?

Was it helpful?

Solution

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 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. 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. If a 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. If a 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. If a 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. If a 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 and b are incompatible, and a compile-time error occurs.

In your case, we're in the third bullet:

  • A is bool?
  • A0 is bool
  • B is bool

... so the result type is bool, and you can assign that to a variable of type bool.

OTHER TIPS

In

bool x;
bool? y = null;
x = y?? true;

y ?? true is syntactic sugar for y.HasValue ? y.GetValueOrDefault() : true. So you are really assigning a bool in the compiler's POV. Take a look at the generated IL to see what's happening behind the C# language's features.

Take a look at ILDasm. Playing with it will teach you a lot about the language!

See remark section on this link and you can know why: http://msdn.microsoft.com/en-us/library/vstudio/ms173224.aspx

A nullable type can contain a value, or it can be undefined. The ?? operator defines the default value to be returned when a nullable type is assigned to a non-nullable type

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top