danielspaniol
danielspaniol

Reputation: 2328

Why can't the ??-operator be applied to generic types, but a null-check can be applied?

If I have a generic function that returns a T or some default value I want to use the ?? operator

T f<T>(T a, T b)
{
    return a ?? b;
}

This fails with the message

Operator '??' cannot be applied to operands of type 'T' and 'T'

I assume this is because T might not be nullable. But I would also assume that the ?? operator above should do the same as

T f<T>(T a, T b)
{
    var a_ = a;
    return a_ != null ? a_ : b;
}

And the second code compiles without a problem.

So why are those cases handled differently even though they should do the same?

Upvotes: 5

Views: 167

Answers (3)

canton7
canton7

Reputation: 42225

From this question on dotnet/csharplang:

The reason for this is that ?? is intended to unwrap the type on the left if the type on hte left is Nullable<T>. In other words, today i can write:

int? x ...;
int y ...;
int z = x ?? y;

So, it's not the case that "x ?? y" translates to "x != null ? x : y". It can translate to "x != null ? x.Value : y".

Since we don't know if T is a value or reference type, we cannot effectively do the transformation. However, when T is constrained to "class" or "struct" (and in the latter case, is a T?), then we can do the transformation.

See the rest of that thread for a wider discussion.

There's a discussion around relaxing this.

Upvotes: 5

Ausl&#228;nder
Ausl&#228;nder

Reputation: 499

What is T struct or class? Thats why it cant return default type.

T fa<T>(T a, T b)where T :class
{
return a ?? b;
}

Upvotes: -1

MPost
MPost

Reputation: 535

Not every object is nullable... Classes are nullable. Therefore, you have to indicate that what you are passing in is a class. Alternatively, use default(T) instead of null, but if you pass in 'int' for T, that will be zero instead of null.

T f<T>(T a, T b)
   where T: class
{
     ....
}

Upvotes: 0

Related Questions