使用泛型类型作为异步方法的返回类型

本文关键字:异步方法 返回类型 泛型类型 | 更新日期: 2023-09-27 18:05:42

前面的问题让我想知道为什么下面的方法会引发编译时错误:

异步方法的返回类型必须是void、Task或Task

public async T MyMethodAsync<T>() where T : Task
{
     // Irrelevant code here which returns a Task
}

既然我们在编译时知道T总是一个Task或派生类型,为什么不能工作?

编辑

我问的原因是一个方法可以返回TaskTask<T>。假设这个方法可以返回任意一个我不想重复代码。

当然,这些都是理论上的,并不是为了生产目的而修改的。

2

找到Lucian Wischik的一篇很棒的文章:为什么必须异步返回Task

使用泛型类型作为异步方法的返回类型

三个问题:

  • 仅仅因为T是"Task或派生类型"并不意味着它是TaskTask<T>。如果我调用MyMethodAsync<MyCustomTask>,而MyCustomTask来自Task,你会期望什么?

  • 编译器在编译方法时需要知道它是在构建一个返回Task还是Task<T>的状态机——它在不同的情况下使用不同的helper类

  • 如果异步方法的返回类型是Task,那么任何return语句都不能指定值;如果返回类型为Task<T>,则任何return语句都必须指定一个可隐式转换为T的值。如何在MyMethodAsync内工作?这有点像说"我的方法是void或返回T -你可以决定何时调用它"。

我不清楚你想要达到什么目的,但基本上这是行不通的。

我想不出MyMethodAsync的有效定义,允许它在编译时不知道该类型是什么或接受某种参数的情况下返回从Task派生的泛型T

如果你真的返回了TaskTask<T>,那么你可以更新你的签名来反映这一事实并避免这个问题。

如果你真的需要从Task派生的一些类型,那么你将需要重写你的逻辑,而不是返回TaskTask<T>,并围绕其他类型。假设这是不可接受的,您将需要放弃async并自己处理状态机。