C# Generic Method with non-nullable generic parameter warns of possible null reference

Viewed 443

When programming today the following situation arose. A generic method accepts a non-nullable generic parameter. The method basically just inserts the generic value into a collection. However, this gives rise to a compiler warning indicating that the generic parameter might be null. At the face of it, it seems to be a bug in the compiler and contradict the design of nullable values. However, I am sure that there is some good explanation that I am not seeing.

Consider the following simplified example of the situation: public void M1<T>(T t, List<object> l) => l.Add(t); The compiler warns that t might be null in l.Add(t).

Also just for completness the following method gives the same error (as expected): public void M1<T>(T? t, List<object> l) => l.Add(t);

Anyone has some good insights into this?

1 Answers

Someone could call:

var list = new List<object>();
M1<string?>(null, list);

Now your list, which should only contain non-nullable objects, contains null. Hence the warning.

If you want to prevent T from being a nullable type, then:

public void M1<T>(T t, List<object> l) where T : notnull
{
    ...
}

This gives you the warning:

M1<string?>(null, new List<object>());
^^^^^^^^^^^
// warning CS8714: The type 'string?' cannot be used as type parameter 'T' in the generic 
// type or method 'C.M1<T>(T, List<object>)'. Nullability of type argument 'string?' doesn't
// match 'notnull' constraint.

If you want to let T be null, but still forbid null values for that t parameter, then:

public void M1<T>([DisallowNull] T t, List<object> l)
{
    ...
}

This gives you the warning:

M1<string?>(null, new List<object>());
            ^^^^
// warning CS8625: Cannot convert null literal to non-nullable reference type.

Of course, if you want to allow null then your l needs to be a List<object?>.

Related