Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 834
comecme Avatar asked Apr 16 '12 08:04

comecme


People also ask

What is nullable types and null coalescing operator in C#?

Nullable types work as a connector between a database and C# code to provide a way to transform the nulls to be used in C# code. Null Coalescing operators simplify the way to check for nulls and shorten the C# code when the developer is dealing with nulls.

What is the use of null coalescing operator?

The null-coalescing operator ?? returns the value of its left-hand operand if it isn't null ; otherwise, it evaluates the right-hand operand and returns its result. The ?? operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.

What happens when we box or unbox nullable types?

Boxing a value of a nullable-type produces a null reference if it is the null value (HasValue is false), or the result of unwrapping and boxing the underlying value otherwise. will output the string “Box contains an int” on the console.

Why we use nullable types in C#?

You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false . However, in some applications a variable value can be undefined or missing.


2 Answers

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 depends on which implicit conversions are available between the types of the operands. In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a, 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 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!

like image 150
AakashM Avatar answered Sep 19 '22 00:09

AakashM


To go all language lawyer, for a moment. From the C# spec (version 4):

7.13

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.

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, 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).

like image 26
Damien_The_Unbeliever Avatar answered Sep 20 '22 00:09

Damien_The_Unbeliever