英文:
Is there something similar to NotNullIfNotNullAttribute for IEnumerable return values?
问题
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:
我知道可以使用 NotNullIfNotNullAttribute
来指定我的方法的返回值可能为 null,仅当输入为 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.
对于返回 IEnumerable<T>
的方法是否有类似的东西?我想告诉编译器,如果输入参数非 null,返回的 IEnumerable
中的所有 元素 都是非 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:
以下是一个最小可复现的示例(fiddle)可供测试:
#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) };
}
英文:
(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) };
}
答案1
得分: 2
我认为你想要的已经是可能的。
在这种情况下,我们想要修改其nullability的输入和输出都是类型T
,这是封闭方法上的类型参数。在这里,我们不需要使用[NotNullIfNotNull]
— 我们可以使用方法类型参数推断来实现我们想要的效果。SharpLab。
// ok
IEnumerable<string> a = GetValuesOrDefault(new[] { "a", null }, defaultValue: "b");
IEnumerable<string> b = GetValuesOrDefault(new[] { "a", "b" }, defaultValue: "b");
// warning: Nullability of reference types in value of type 'IEnumerable<string?>' doesn't match target type 'IEnumerable<string>'.
IEnumerable<string> c = GetValuesOrDefault(new[] { "a", null }, defaultValue: null);
IEnumerable<T> GetValuesOrDefault<T>(IEnumerable<T?> valuesFromSomewhere, T defaultValue)
{
return valuesFromSomewhere.Select(x => x ?? defaultValue);
}
这给了我们在这里想要的控制点:如果输入的defaultValue
是非可空的,那么结果的IEnumerable
也具有非可空的类型参数。如果输入的defaultValue
可能为 null,那么结果的IEnumerable
具有可空的类型参数。
英文:
I think what you want is already possible.
In this case, both the input and output whose nullability we want to modify are of type T
, a type parameter on the enclosing method. We don't need [NotNullIfNotNull]
here — we can just use method type argument inference to achieve what we want. SharpLab.
// ok
IEnumerable<string> a = GetValuesOrDefault(new[] { "a", null }, defaultValue: "b");
IEnumerable<string> b = GetValuesOrDefault(new[] { "a", "b" }, defaultValue: "b");
// warning: Nullability of reference types in value of type 'IEnumerable<string?>' doesn't match target type 'IEnumerable<string>'.
IEnumerable<string> c = GetValuesOrDefault(new[] { "a", null }, defaultValue: null);
IEnumerable<T> GetValuesOrDefault<T>(IEnumerable<T?> valuesFromSomewhere, T defaultValue)
{
return valuesFromSomewhere.Select(x => x ?? defaultValue);
}
This gives us the point of control we want here: If the defaultValue
going in is non-nullable, the result IEnumerable has a non-nullable type argument. If the defaultValue
going in may be null, the result IEnumerable has a nullable type argument.
答案2
得分: 1
不幸的是,目前没有这样的功能(至少通过属性)。同样的问题也出现在任务中,可以在这里(或这里)找到相关讨论,但根据评论,目前似乎只考虑了特定于任务和async
-await
情况(也请参考这个讨论)。
英文:
No, sadly but currently there is no such thing (at least via attributes). There same issue can be observed with tasks, which is discussed here (or this one), but based on comments it seems that at the moment only task-specific and async
-await
case are taken into consideration (see also this discussion).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论