Reputation: 8047
I'm converting some old C# code to use C# 8, and have encountered this problem:
class MyList<T> : IMyEnumberable<T>
{
public T GetDefault()
{
return default;// a default expression introduces a null value when 'T' is a non-nullable reference type
}
}
It failed to compile and says
a default expression introduces a null value when 'T' is a non-nullable reference type
I'm not sure what is the problem here - any explanations?
Upvotes: 0
Views: 419
Reputation: 42225
The problem is that someone could do:
var list = new MyList<string>();
string d = list.GetDefault();
Because they created a MyList<string>
, then T
is string
, (i.e. a non-nullable string). Therefore because GetDefault()
returns a T
, this should mean that it returns a non-nullable string.
However if they call GetDefault()
, that will return default(string)
, which is null
. They'll get null
when they weren't expecting one!
You can't prevent someone from creating a MyList<string>
: there's no syntax to say "T
must only be a nullable type, and must not be a non-nullable type".
If you constrain T
to be a struct
or class
, you can write:
class MyList<T> : IMyEnumberable<T> where T : struct // or : class
{
public T? GetDefault()
{
return default;
}
}
Alternatively, you can add a [MaybeNull]
to the return type of GetDefault()
to say that, even though it returns T
(and T
may be non-nullable), this method might actually return null
.
(Note that currently this only affects callers of GetDefault()
, and not the actual body, so you'll still need the null-suppressing operator !
. It looks like this will change soon):
using System.Diagnostics.CodeAnalysis;
class MyList<T> : IMyEnumberable<T>
{
[return: MaybeNull]
public T GetDefault()
{
return default!;
}
}
Upvotes: 2
Reputation: 2000
You don't put any constraint to your generic T, so basically T can be anything. That's why you got default null.
var test = new MyList<SomeClass>().GetDefault(); // This gives you null
var test2 = new MyList<int>().GetDefault(); // This gives you 0
If you want to force T must be non-nullable, use this.
class MyList<T> where T : struct
Upvotes: 1