Я реализовал следующие методы расширения для IDictionary
, которые попытаются получить значение из словаря, но вернут значение по умолчанию (либо default(T)
, либо предоставленное пользователем), если ключ не существует. Первый метод без значения, предоставленного пользователем, будет вызывать другой метод с default
.
[return: MaybeNull]
public static T GetValueOrDefault<TKey, T>(this IDictionary<TKey, T> source, TKey key) where TKey : notnull
{
return GetValueOrDefault(source, key, defaultValue: default);
}
[return: MaybeNull]
public static T GetValueOrDefault<TKey, T>(this IDictionary<TKey, T> source, TKey key, [AllowNull] T defaultValue) where TKey : notnull
{
if (source is null) throw new ArgumentNullException(nameof(source));
if (key is null) throw new ArgumentNullException(nameof(key));
if (source.TryGetValue(key, out var item))
{
return item;
}
return defaultValue;
}
С .NET SDK 3.1.100 этот код компилируется нормально. Однако с новейшим .NET SDK 5.0.101 я получаю следующее сообщение об ошибке:
ошибка CS8620: аргумент типа 'IDictionary ‹TKey, T›' не может использоваться для параметра 'source' типа 'IDictionary ‹TKey, T?›' в 'T? DictionaryExtensions.GetValueOrDefault ‹TKey, T?› (IDictionary ‹TKey, T?› Source, TKey key, T? DefaultValue) 'из-за различий в допустимости пустых значений ссылочных типов.
Он жалуется на использование default
в GetValueOrDefault(source, key, defaultValue: default)
. Использование default!
, конечно, подавляет сообщение об ошибке, но предполагается, что значение допускает обнуление (отсюда AllowNullAttribute
на defaultValue
). Или, может быть, он выводит, что T
допускает значение NULL из-за атрибута и использования и не разрешает вызов с T
, не допускающим значения NULL?
Ошибка возникает только в том случае, если T
является общим и не ограничивается class
. Например, следующий код не вызывает ошибки:
var dict = new Dictionary<string, string>();
dict.GetValueOrDefault("key", null);
Я делаю что-то неправильно? Были ли ужесточены ограничения на ссылочные типы, допускающие значение NULL, в новой версии .NET? Это просто ошибка .NET SDK 5.0.101?