Pergunta

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.

Foi útil?

Solução

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.

Outras dicas

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.

int result = input == null ? input : 10;

You got your condition mixed in the second case - you probably meant:

int result = input != null ? input : 10;

Now this won't compile because both types in use with the ternary operator must be exactly identical (and int? is not the same as int) - you can use a simple cast as a solution:

int result = input != null ? (int)input : 10;

A more concise explantion:

int? NULL_Int = 1;
int NORM_Int = 2;

NULL_Int = NORM_Int;  // OK

NORM_Int = NULL_Int;  // NO, you can't assign a null to an int
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top