Skip to content

[API Proposal]: Add MaybeNullIfNull attribute #115990

Open
@voroninp

Description

@voroninp

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.CollectionsuntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions