Consider the following code:
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace dla.test2{
internal class Test{
public static void Main(){
var map=new Dictionary<string,string>(){
["hello"]="world"
};
using var foo=new FormUrlEncodedContent(map);
}
}
}
Calling the constructor of FormUrlEncodedContent yields the following compiler warning at build-time:
Warning CS8620 Argument of type 'Dictionary<string, string>' cannot be used for parameter 'nameValueCollection' of type 'IEnumerable<KeyValuePair<string?, string?>>' in 'FormUrlEncodedContent.FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)' due to differences in the nullability of reference types.
The documentation for FormUrlEncodedContent indicates the constructor should accept an IEnumerable<KeyValuePair<string,string>>?. My map variable, being a Dictionary<string,string>, would presumably implement the interface IEnumerable<KeyValuePair<string,string>> so I'd expect there to be no problem here. So why the warning?
I'm using Visual Studio 16.8.0 targeting NETCore5.
I feel like there are actually a couple of questions here:
The latter is easier to answer. The former, not so much (you'd have to ask Microsoft).
I don't have .NET 5 installed yet. But I can reproduce the exact same warning in .NET Core 3.1 with this code:
It's possible to infer from the warning you copy/pasted into your question what the actual declaration of the .NET 5 version of the
FormUrlEncodedContentclass constructor must be, so I just wrote an example that doesn't require .NET 5 to be installed.And indeed, if we look at the source code, we can see the actual declaration of that constructor:
This tells me that the documentation is inaccurate, if not outright incorrect. I haven't been following the changes to the framework for supporting nullable reference types, so I'm not sure if the documentation is expected to show nullable type parameters for this sort of situation. Seems to me it should, but clearly it's not. At the very least, it's surprising to me that the documentation shows the
nameValueCollectionparameter itself as nullable (which in fact it's not), never mind that it shows theKeyValuePair<TKey, TValue>type parameters as non-nullable, when in fact they are nullable.But regardless, by understanding what the actual method signature is in .NET 5, we can then say that the warning is there simply because indeed, your call involves passing a type that is inconsistent with the nullability of the type parameters.
Why should this generate a warning? Well…while we know in this case no code will be writing to the nullable values in the values of the enumerable, there's no compile-time guarantee of this. Since your object is returning objects where the values are non-nullable references, and you pass this to a method that is declared as accepting values which are nullable, that means that in theory, that method could modify those nullable values by setting them to
null, violating your own code's assumption that the values are non-nullable.