Description
Description
For a generic parameter T
on a class with no type constraints indicating nullability, Unknown
would seem most appropriate nullability state to return from NullabilityInfoContext
because there are no constraints on that type with respect to nullability.
However, the value returned seems to depend on whether the type is declared in a nullable or non-nullable context
Reproduction Steps
public static void Main()
{
var context = new NullabilityInfoContext();
var fooInfo = context.Create(typeof(Foo<string?>).GetConstructors().Single().GetParameters().Single());
Console.WriteLine(fooInfo.WriteState); // NotNull (I would expect Unknown; NotNull is clearly wrong here given that I can make Foo<string?>)
var barInfo = context.Create(typeof(Bar<string?>).GetConstructors().Single().GetParameters().Single());
Console.WriteLine(barInfo.WriteState); // Unknown
}
#nullable disable
private class Foo<T> { public Foo(T t) { } }
#nullable enable
#nullable disable
private class Bar<T> { public Bar(T t) { } }
#nullable enable
Expected behavior
Consistently returns Unknown.
Actual behavior
Sometimes returns NotNull.
Regression?
No response
Known Workarounds
No response
Configuration
VS 17.0.2, .NET 6, Windows 10 x64.
I don't have any reason to believe this is configuration specific.
Other information
C#9 allows for both T
and T?
to be used in generic classes even without any constraint that indicates whether or not T
can be null:
class Generic<T> { public void Foo(T a, T? b) { } }
It's unclear what NullabilityInfoContext
should return when reflecting over such types. On one hand, both could be either non-nullable or nullable depending on the particular generic argument that ends up getting used, which makes Unknown
seem reasonable for both from that perspective.
On the other hand, it seems nice to be able to differentiate between the two in some way. Perhaps it makes sense to add another null state that explicitly represents the case of NotNullIfGenericArgumentIsNonNullableReferenceType
?