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

时间:2014-05-29 17:32:14

标签: c# .net generics async-await

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

  

异步方法的返回类型必须为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发现了一篇很棒的文章: Why must async return Task

2 个答案:

答案 0 :(得分:13)

三个问题:

  • 仅因为T是“Task或派生类型”并不意味着它是TaskTask<T>。如果我致电MyMethodAsync<MyCustomTask> MyCustomTask来自Task,那么您会期待什么?

  • 编译器在编译方法时需要知道它是否正在构建一个返回TaskTask<T>的状态机 - 它在不同情况下使用不同的辅助类

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

目前尚不清楚你在这里想要达到的目标,但基本上这不会起作用。

答案 1 :(得分:-1)

我无法想到MyMethodAsync的有效定义,它允许它返回从T派生的通用Task,而不知道在编译时该类型是什么或采用参数某种。

如果您确实要返回TaskTask<T>,那么您可以更新签名以反映这一事实并避免此问题。

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