With the following understanding about null coalescing operator (??) in C#.
int? input = -10;
int result = input ?? 10;//Case - I
//is same as:
int result = input == null? input : 10; // Case - II
While, by definition and usage, Case I and Case II are same.
It is surprising to see that in Case-I compiler is able to implicitly cast int? to int while in Case-II it shows error: 'Error 1 Cannot implicitly convert type 'int?' to 'int'"
What is it that I am missing about null-coalescing operator?
Thanks for your interest.
To make the second case work with the ternary operator, you could use the following:
int result = input != null ? input.Value : 10;
The Value
property of the Nullable<T>
type returns the T
value (in this case, the int
).
Another option is to use Nullable<T>.HasValue
:
int result = input.HasValue ? input.Value : 10;
The myNullableInt != null
construct is only syntactic sugar for the above HasValue
call.
This behavior you have observed for the null-coalescing operator ??
is a documented language feature, see section 7.13 of the C# 4.0 Language Specification for more details.
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.
See section 7.14 for why the conditional operator a ? b : c
works differently.
Download the specification to read both in completeness at your leisure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With