(This is a question about C# nullable reference types and generics.)
I know that I can use NotNullIfNotNullAttribute
to specify that the return value of my method may be null if, and only if, an input is null:
[return: NotNullIfNotNull(nameof(defaultValue))]
public T? GetValueOrDefault<T>(T? defaultValue)
{
return GetValueFromSomewhere<T>() ?? defaultValue;
}
Is there something similar for methods returning IEnumerable<T>
? I'd like to tell the compiler that all elements of the returned IEnumerable are non-null if the input parameter is non-null.
[return: ???]
public IEnumerable<T?> GetValuesOrDefault<T>(T? defaultValue)
{
return GetValuesFromSomewhere<T>().Select(x => x ?? defaultValue);
}
Here's a MCVE (fiddle) to play around with:
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
public class Program
{
public static void Main()
{
string? s1 = GetValueOrDefault<string>(null);
string s2 = GetValueOrDefault<string>(""); // works, C# realizes that the return value can't be null
IEnumerable<string?> e1 = GetValuesOrDefault<string>(null);
IEnumerable<string> e2 = GetValuesOrDefault<string>(""); // I want to get rid of the warning here
}
[return: NotNullIfNotNull(nameof(defaultValue))]
public static T? GetValueOrDefault<T>(T? defaultValue)
{
return GetValueFromSomewhere<T>() ?? defaultValue;
}
public static IEnumerable<T?> GetValuesOrDefault<T>(T? defaultValue)
{
return GetValuesFromSomewhere<T>().Select(x => x ?? defaultValue);
}
// Dummy placeholders for my MCVE. My real methods read values from my DB repository.
private static T? GetValueFromSomewhere<T>() => default(T);
private static IEnumerable<T?> GetValuesFromSomewhere<T>() => new T?[] { default(T) };
}