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

drs*_*222 6 c# generics async-await nullable-reference-types

我的情况类似于描述的可能返回 default(T) 的异步通用方法的正确可为空注释

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

    public async Task<T> GetAsync<T>()
    {
        // sometimes returns default(T)!;
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

    public async Task<string?> GetAsync()
    {
        // sometimes returns default(string)!;
    }
Run Code Online (Sandbox Code Playgroud)

有没有办法让调用者知道它可以为空而不添加通用约束?

编辑:澄清我的意思是让编译器知道任务中的值可能为空。我想反过来也是如此。我最感兴趣的是这应该如何与新的 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
Run Code Online (Sandbox Code Playgroud)

编辑:我可以做这样的事情就好了

    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
Run Code Online (Sandbox Code Playgroud)

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

小智 -3

这里类似的主题:可空类型作为泛型参数可能吗?

这里的问题是我们不知道类型T是什么,我的意思是它是类还是结构。如果它始终是 struct ,那么我建议使用Nullable<T>or T?with constraint where T : struct。但如果根据定义它可以是类,则类可以为 null,因为它是引用类型。

您可以告诉调用者如果没有限制他可能会得到什么的唯一方法是使用/// <summary>itsme86 提到的或给方法更有意义的名称,例如。GetOrDefaultAsync()

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

  • 这并不完全正确,因为我们在非异步方法上也有同样的问题,但您可以使用属性告诉编译器结果可能为 null。 (3认同)