Reputation: 2556
With the following code
abstract class Base
{
protected abstract T? GetValue<T>([CallerMemberName] string propertyName = "");
}
class Derived : Base
{
protected override T GetValue<T>([CallerMemberName] string propertyName = "")
{
return default;
}
}
the compiler tells me at return default;
that I have a CS8603 "Possible null reference return" which is true. However if I append a ?
to the return type of that method so that reads (like the abstract method) protected override T? GetValue<T>([CallerMemberName] string propertyName = "")
the compiler tells me
How do I tell the compiler my intent that GetValue<T>
might return a null reference and not that the return type of that method should be Nullable<T>
?
Upvotes: 4
Views: 9260
Reputation: 2254
Returning T?
instead of T
worked for me.
protected override T? GetValue<T>([CallerMemberName] string propertyName = "")
{
return default;
}
Or, remove <Nullable>enable</Nullable>
from your .csproj
file
Upvotes: 0
Reputation: 2556
The solution was to place the [return: MaybeNull]
attribute on the method override as follows:
[return: MaybeNull]
protected override T GetValue<T>([CallerMemberName] string propertyName = "")
{
return default;
}
The compiler now no more lists warning CS8603.
Upvotes: 6
Reputation: 142288
You can use default
generic constraint to make it compile:
abstract class Base
{
protected abstract T? GetValue<T>([CallerMemberName] string propertyName = "");
}
class Derived : Base
{
protected override T? GetValue<T>([CallerMemberName] string propertyName = "") where T : default
{
return default;
}
}
But for value types default(T)
will be returned not default(Nullable<T>)
so it needs to be invoked with nullable value type for type parameter to achieve desired behaviour.
You can try to workaround by having 2 methods with different type constraints and dummy T? == null
parameter:
abstract class Base
{
public abstract T? GetValue<T>([CallerMemberName] string propertyName = "", T? _ = null) where T : struct;
public abstract T? GetValue<T>([CallerMemberName] string propertyName = "", T? _ = null) where T : class;
}
class Derived : Base
{
public override T? GetValue<T>([CallerMemberName] string propertyName = "", T? _ = null) where T : struct
{
return default;
}
public override T? GetValue<T>([CallerMemberName] string propertyName = "", T? _ = null) where T : class
{
return default;
}
}
But it's up to you to decide how usable/ugly this is)
Upvotes: 1