Open
Description
Background and motivation
Sometimes several parameters of the same type affect the nullability of result value.
For example, here are the methods from CollectionExtensions:
public static TValue? GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key) =>
dictionary.GetValueOrDefault(key, default!);
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
if (dictionary is null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
return dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
}
Pay attention to the bang (!) operator used in the first method.
API Proposal
Now Imagine we could apply the attribute to the second method:
[return: MaybeNullIfNull(namef(defultValue)]
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue? defaultValue) // defaultValue is nullable now.
{
if (dictionary is null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
return dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
}
In this case bang operator won't be required, and compiler can infer nullability of returned value both based on the type of the dictionary and default value.
API Usage
var dict1 = new Dictionary<int, string>();
string str1 = dict1.GetValueOrDefault(1, null); // compiler emits warning/error because method can return null;
string str2 = dict1.GetValueOrDefault(1, "abc"); // compiler is happy.
var dict2 = new Dictionary<int, string?>();
string str3 = dict2.GetValueOrDefault(1, "abc"); // compiler complains.
Alternative Designs
No response
Risks
No response