4
votes

I have this code:

public T? Foo<T>()
    where T : class?
{
    return null;
}

It gives an error that is logical and expected:

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.

Now I add one more constraint:

public T? Foo<T>()
    where T : class?, IDisposable // Could be any interface I guess
{
    return null;
}

Now interestingly enough error has just disappeared. Though it really seems to me we have conflicting constraints since interface is non-nullalbe while class? is.

Am I missing something here or is there a trouble with compiler?

1
You need IDisposable?. Yes it's confusing. - canton7
Yeah, I tested with with ?, and it compiles. Ironically enough it also compiles like that where T : class, IDisposable? - Ilya Chernomordik
It seems the whole constraint is non-nullable if at least one constraint is non-nullable - Ilya Chernomordik
@IlyaChernomordik sounds conclusive, since the constraints are AND-connected. - Holger

1 Answers

5
votes

The generic type constraint where T : IDisposable means "T must be non-nullable and must implement IDisposable". Where you have multiple generic type constraints of differing nullabilities, the constraint overall is only nullable if all constraints are nullable.

So the fact that class? is nullable gets overridden by the fact that IDisposable is not.

You need where T : class?, IDisposable?.