You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NullabilityInfoContext does not report the correct nullability for method in generic base class. #63555
Let's say I have the following class defined in nullable enabled context:
private class NonNullableValuesDictionary : Dictionary<string, object> { }
If I try to add a null value to the object, I get a compiler error:
var dictionary = new NonNullableValuesDictionary();
dictionary.Add("a", null); // CS Cannot convert null literal to non-nullable reference type
However, I can't replicate this compiler behavior with NullabilityInfoContext even though it seems to me that the compiler must be reading the same metadata in order to issue that warning.
Reproduction Steps
public static void Main()
{
var context = new NullabilityInfoContext();
var addMethod = typeof(NonNullableValuesDictionary).GetMethod("Add")!;
var info = context.Create(addMethod.GetParameters()[1]);
Console.WriteLine(info.WriteState); // Nullable
}
private class NonNullableValuesDictionary : Dictionary<string, object> { }
Expected behavior
I would expect the code above to print "NotNull" instead.
Actual behavior
Prints "Nullable".
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.
This is by design, at runtime there is no way to distinguish if the NonNullableValuesDictionary was Dictionary<string, object> or Dictionary<string, object?> at runtime the DeclaringType of refected method var addMethod = typeof(NonNullableValuesDictionary).GetMethod("Add")!; will be just Dictionary<string, object> without any nullability info we could determine object? was null.
Therefore in order to determine nullability of the Dictionary<string, object>.Add(string, object) we use the original generic definition of the type: Dictionary<TKey, TValue> .Add(TKey, TValue) where TKey not null and TValue is nullable
@buyaa-n if there is no way to tell, how does the compiler differentiate (or can the compiler only do it if the derived type is defined in the same compilation?)?
I guess i should have said that there is no way to distinguish that in reflection, because compiler does not provide any nullability info for those generic parameters (reflection uses compiler provided NullableAttribute or NullableContextAttribute to determine nullability, and it is impossible to provide that info current design)
The compiler nullability analysis and this reflection API are do not work same
Activity
krwq commentedon Jan 10, 2022
cc: @buyaa-n
buyaa-n commentedon Jan 10, 2022
This is by design, at runtime there is no way to distinguish if the
NonNullableValuesDictionarywasDictionary<string, object>orDictionary<string, object?>at runtime the DeclaringType of refected methodvar addMethod = typeof(NonNullableValuesDictionary).GetMethod("Add")!;will be justDictionary<string, object>without any nullability info we could determineobject?was null.Therefore in order to determine nullability of the
Dictionary<string, object>.Add(string, object)we use the original generic definition of the type:Dictionary<TKey, TValue> .Add(TKey, TValue)whereTKeynot null andTValueis nullablemadelson commentedon Jan 10, 2022
@buyaa-n if there is no way to tell, how does the compiler differentiate (or can the compiler only do it if the derived type is defined in the same compilation?)?
buyaa-n commentedon Jan 10, 2022
I guess i should have said that there is no way to distinguish that in reflection, because compiler does not provide any nullability info for those generic parameters (reflection uses compiler provided
NullableAttributeorNullableContextAttributeto determine nullability, and it is impossible to provide that info current design)The compiler nullability analysis and this reflection API are do not work same
madelson commentedon Jan 10, 2022
@buyaa-n but when I decompile my assembly with dotpeek it looks like the nullable metadata is there:
Original:
Decompiled:
Aren't those attributes describing the nullability of the generic parameters for
Dictionary?buyaa-n commentedon Jan 11, 2022
Hm, that actually looks feasible compared to, reopening the issue, thanks!
Fix several bugs in NullabilityInfoContext.