异步元组 return 是否有等效的 NotNullWhen C# 模式?

Is there an equivalent NotNullWhen C# pattern for async tuple return?

在具有可空类型的 C# 中,可以实现 'TryGet' 智能空检查,例如,

bool TryGetById(int id, [NotNullWhen(returnValue: true)] out MyThing? myThing)

这允许调用者跳过对输出变量 myThing 的空值检查。

不幸的是,Async 不允许输出参数,并且使用 Tuple return 的模式不允许进行这种智能 NotNull 检查(至少,据我所知是这样)。有替代方案吗?

有什么方法可以在异步元组 return 类型上使用 'NotNullWhen' 等价物,例如,

Task<(bool Ok, [NotNullWhen(returnValue: true)] MyThing? MyThing)> TryGetById(int id)

值元组 还没有实现此功能(目前)。然而!从 C#9 你可以 roll-your-own struct (甚至更好C#10 记录 struct) 与 MemberNotNullWhen.

MemberNotNullWhenAttribute Class

Specifies that the method or property will ensure that the listed field and property members have non-null values when returning with the specified return value condition.

注意:您将需要重新实现所有 tupley 优点,例如平等等。

世界上最人为的例子接踵而至

#nullable enable

public readonly struct Test
{
   [MemberNotNullWhen(returnValue: true, member: nameof(Value))]
   public bool IsGood => Value != null;

   public string? Value { get; init; }
}

public static Task<Test> TryGetAsync()
   => Task.FromResult(new Test {Value = "bob"});

public static void TestMethod(string bob)
   => Console.WriteLine(bob);

用法

var result = await TryGetAsync();
if (result.IsGood)
   TestMethod(result.Value); // <= no warning

如果您拥有 MyThing 的实施,您可以这样做

public class MyThing
{
    public static readonly MyThing Empty = new();
 // all other properties etc
}

然后使您的方法签名永远不会 return null Mything

public async Task<(bool Ok, MyThing MyThing)> TryGetById(int id)
{
    var something = await FindSomething(id);

    return (something == null) 
           ? (false, MyThing.Empty);
           : new (true, something);
}

var result = await TryGetById(420);
if(result.Ok) // whatever