告诉调用者,一个`async Task<T>`方法可能会返回null。

8

我的情况类似于描述在 Proper nullable annotation for async generic method that may return default(T)中的那个问题。

但是,我想知道让调用者知道"返回值"可能为空的正确方式。

    public async Task<T> GetAsync<T>()
    {
        // sometimes returns default(T)!;
    }

如果这不是一个异步方法,我可以使用MaybeNull属性。

    [return: MaybeNull]
    public T Get<T>()
    {
        // sometimes returns default(T)!;
    }

如果这不是通用的,我就可以使用?语法。

    public async Task<string?> GetAsync()
    {
        // sometimes returns default(string)!;
    }

有没有一种方法可以让调用者知道它可能为空,而不添加泛型约束?
编辑: 澄清一下,我的意思是让编译器知道任务中的值可能为空。 我认为反过来也是正确的。 我主要关心的是这如何与新的C#可空引用语法配合使用。
我可以做到像这样的事情。
    var a = await GetAsync<string?>(); // a is null
    var b = await GetAsync<int?>(); // b is null
    var c = await GetAsync<string>(); // c is null.  Wait string is not supposed to be null and the compiler won't warn you if you use it!
    var d = await GetAsync<int>(); // d is 0

编辑: 我可以很好地做类似这样的事情

    var a = await Get<string?>(); // a is null
    var b = await Get<int?>(); // b is null
    var c = await Get<string>(); // c is null.  
    var d = await Get<int>(); // d is 0

建议类似于可空引用类型:如何指定“T?”类型而不限制于类或结构,但 Box 类可以修改以在我无法更改 Task 实现时提供适当的警告。


1
添加一个 /// 摘要标签? - itsme86
@itsme86,当我提到调用者时,我指的是应用于调用代码的编译器。 - drs9222
4
https://github.com/dotnet/roslyn/issues/30953#issuecomment-619290623 - GSerg
看起来你需要等待C#9,或者为每个结构体/类约束编写重载。 - Jeremy Lakeman
显示剩余3条评论
2个回答

1
在C# 8中,您无法表达这个概念,因为您无法将[MaybeNull]属性应用于Task<T>的类型参数。
在C# 9中,您只需使返回类型可为空。
public async Task<T?> GetAsync<T>()
{
    // sometimes returns default(T)!;
}

-3

这里有一个类似的话题:可空类型作为泛型参数是否可行?

问题在于我们不知道 T 是什么类型,我的意思是它是类还是结构体。如果它总是结构体,那么我建议使用带有约束条件 where T : structNullable<T>T?。但是,如果它可以是类,按照定义,类可以为 null,因为它是引用类型。

唯一能告诉调用者没有约束条件时可能得到什么的方法是使用 /// <summary>,就像 itsme86 提到的那样,或者给方法更有意义的名称,例如 GetOrDefaultAsync()

编辑: 参考 Stefan 的答案,使用一些函数式编程技巧创建返回类型的包装器,指示返回的对象是否具有值,是一个好的解决方案。


3
这并不完全正确,因为我们在非异步方法上也有同样的问题,但你可以使用属性告诉编译器结果可能为空。 - drs9222
在这种特定情况下,您需要使用的属性不允许在源代码中使用。您可以声明该属性的副本,可能会欺骗编译器,但是当您尝试使用它时,会告诉您“CS8623:不允许显式应用'System.Runtime.CompilerServices.NullableAttribute'”。 - Lasse V. Karlsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接