- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.2k
Description
As part of updating some OAuth provider libraries to target .NET 5 using preview 6 (see aspnet-contrib/AspNet.Security.OAuth.Providers#438), I've come across an issue with new nullable annotations I'm not sure of how to resolve correctly.
The FormUrlEncodedContent type has been updated to add nullable annotations (see #33268) and now the constructor takes an IEnumerable<KeyValuePair<string?, string?>>.
A common existing pattern to populate the values for an instance of FormUrlEncodedContent was to use a Dictionary<string, string>, but that now generates an CS8620 warning.
However simply changing the dictionary to use string? then generates CS8714 because the key cannot be null.
It's possible to fix the warning by casting the dictionary to IEnumerable<KeyValuePair<string?, string?>>, but then Visual Studio suggests the cast is redundant and can be removed.
The redundant cast and warnings can be eliminated by using a list or array of KeyValuePair<string?, string?>, but that's much more verbose.
Below is a simple program that demonstrates different approaches I took to try and fix the warning.
using System.Collections.Generic;
using System.Net.Http;
#nullable enable
namespace FormUrlEncodedContentNullable
{
    class Program
    {
        static void Main()
        {
            var dictionary = new Dictionary<string, string>
            {
                ["foo"] = "bar"
            };
            _ = new FormUrlEncodedContent(dictionary); // CS8620
            _ = new FormUrlEncodedContent((IEnumerable<KeyValuePair<string?, string?>>)dictionary); // OK, but says cast is redundant
            var nullableValueDictionary = new Dictionary<string, string?>
            {
                ["foo"] = "bar"
            };
            _ = new FormUrlEncodedContent(nullableValueDictionary); // CS8620
            var nullableDictionary = new Dictionary<string?, string?> // CS8714
            {
                ["foo"] = "bar"
            };
            _ = new FormUrlEncodedContent(nullableDictionary);
            var listOfKvps = new List<KeyValuePair<string?, string?>>
            {
                new KeyValuePair<string?, string?>("foo", "bar")
            };
            _ = new FormUrlEncodedContent(listOfKvps); // OK, but verbose
            var arrayOfKvps = new[]
            {
                new KeyValuePair<string?, string?>("foo", "bar")
            };
            _ = new FormUrlEncodedContent(arrayOfKvps); // OK, but verbose
        }
    }
}For now I've settled with the cast, but none of the above approaches seem correct to me.
What is the "correct" fix for this code pattern for .NET 5 when nullable is in use? It doesn't seem to be resolvable without suppressing warnings or making the code a lot more verbose that it was before.