Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mark a default return value in C# 8 as nullable for classes only? [duplicate]

I'm currently trying to apply the new C# 8.0 non-nullable reference type feature to existing code, and don't know how to fix the CS8603 warning in the following data deserialization method:

T ReadOptional<T>() where T : IEntity, new()
{
    if (ReadBoolean())
    {
        T instance = new T();
        instance.Read(this); // IEntity method
        return instance;
    }
    else
    {
        // CS8603 Possible null reference return.
        return default;
    }
}

As you can see, the method may return null (classes) / default (structs) if a preceeding boolean was false, otherwise it returns a T instance which can be anything implementing IEntity.

However, I cannot mark the return type as T?, because it would actually not return null if T is a struct, as correctly complained about by the compiler error CS8627:

// CS8627: A nullable type parameter must be known to be a value type or non-nullable
// reference type. Consider adding a 'class', 'struct', or type constraint.
T? ReadOptional<T>() where T : IEntity, new()
  • I cannot fix this by ensuring that T has a class constraint as I also expect struct instances to work with this method (returning default).
  • I cannot create an overload with T having a struct constraint as overloads cannot differ only by constraints.
  • I could create differently named methods, but that will break the library interface and by far too much code dependent on it.

Is there any syntax to fix the non-nullable warning without breaking the possibility of returning default instances for structs?

like image 697
Ray Avatar asked Jan 01 '23 06:01

Ray


1 Answers

EDIT: There's a slightly improved solution posted here.

Browsing through a similar C# 8.0 question here, I filled a gap in my knowledge about nullable reference types: There's a null-forgiving operator ! which can fix the warning for me right here:

T ReadOptional<T>() where T : IEntity, new()
{
    if (ReadBoolean())
    {
        T instance = new T();
        instance.Read(this); // IEntity method
        return instance;
    }
    else
    {
        return default!; // <-- note the exclamation mark
    }
}
like image 150
Ray Avatar answered Jan 03 '23 18:01

Ray