У меня есть такой метод расширения:
[return: MaybeNull]
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
where TKey : notnull
where TValue : notnull {
if (dictionary.TryGetValue(key, out TValue value)) return value;
else return default!;
}
Это отлично работает. Если бы я назвал его ожидающим ненулевое значение, компилятор предупреждает меня, что результаты могут быть нулевыми, а это именно то, что я хочу.
Однако, если у меня есть другой метод, который вызывает GetValueOrDefault
, и я забудьте добавить [return: MaybeNull]
, компилятор не предупредит меня вообще. Вот запутанный пример, чтобы объяснить мою проблему:
public static TValue SomeOtherMethod<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
where TKey : notnull
where TValue : notnull
=> dictionary.GetValueOrDefault(key); // No warning this could be null
...
var dictionary = new Dictionary<string, string>() {
["hello"] = "world"
};
string s1 = dictionary.GetValueOrDefault("foo"); // Compiler warning
string s2 = dictionary.SomeOtherMethod("foo"); // No compiler warning
int s2Len = s2.Length; // Visual Studio states "s2 is not null here", even though it absolutely is!
Я довольно плохо знаком с C# 8.0 обнуляемыми ссылочными типами, особенно с использованием дженериков. Я что-то пропустил, чтобы заставить это работать? Без предупреждения компилятора создается впечатление, что он отрицает цель использования C# 8.0 обнуляемых типов. Я впадаю в ложное чувство безопасности, что не могу пропустить исключение NullReferenceException, особенно когда Visual Studio заверяет меня, что «s2 здесь не равен нулю», даже если это абсолютно так.