У меня есть Dictionary<string,string> параметров, и я хочу создать FormUrlEncodedContent. См. Следующий пример кода:

var message = new Dictionary<string,string> {{"example", "example"}};
var content = new FormUrlEncodedContent(message);

Этот код отлично работает с отключенными значениями NULL, но его включение приводит к предупреждению (а поскольку у нас включены WarningsAsErrors, сборка завершается ошибкой).

Argument of type 'System.Collections.Generic.Dictionary<string,string>' cannot
be used for parameter 'nameValueCollection' of type 
'System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string?,string?>>'
in 'System.Net.Http.FormUrlEncodedContent.FormUrlEncodedContent'
due to differences in the nullability of reference types.

Я работал над этим, выполняя message.Select(kvp => new KeyValuePair<string?, string?>(kvp.Key, kvp.Value)), но это очень многословно, грубо и, вероятно, медленнее.

Какие-либо предложения? Мне не хватает очевидного способа приведения этого значения, или класс FormUrlEncodedContent не подходит для принятия KeyValuePair<string?, string?>?

1
Mavvie 4 Май 2021 в 20:09

3 ответа

Лучший ответ

Лучшее решение, которое я знаю для текущей C # является приведение к типу параметра (хотя ! это тоже хорошо): #nullable enable using System.Collections.Generic; using System.Net.Http; var message = new Dictionary<string,string> {{"example", "example"}}; var content = new FormUrlEncodedContent((IEnumerable<KeyValuePair<string?, string?>>)message);

Проблема здесь в том, что структуры и параметры типа класса инвариантны. Из-за этого мы не разрешаем неявное преобразование KeyValuePair<string, string>, например, в KeyValuePair<string?, string?>, даже если это не является реальной проблемой безопасности.

Решение аналогичной проблемы было предложено для Task<T>. Возможно, язык должен представить решение, которое работает как в сценарии Task, так и в KeyValuePair, и, возможно, его можно будет распространить на другие сценарии.

1
Rikki Gibson 4 Май 2021 в 21:55

! (допускающий нулевое значение ) оператор делает свое дело:

var message = new Dictionary<string, string> { { "example", "example" } };
var content = new FormUrlEncodedContent(message!);
1
Christian Held 4 Май 2021 в 20:34

Кажется, я нашел способ обойти это, используя as:

var content = new FormUrlEncodedContent(
                message.AsEnumerable() as IEnumerable<KeyValuePair<string?,string?>>);
0
Mavvie 4 Май 2021 в 19:08