之前的一个问题让我想知道为什么以下方法会引发编译时错误:
异步方法的返回类型必须为void,Task或Task
public async T MyMethodAsync<T>() where T : Task
{
// Irrelevant code here which returns a Task
}
由于我们在编译时知道T始终是Task
或派生类型,为什么这不起作用?
修改
我问的原因是方法可能会返回Task
或Task<T>
。假设该方法可以返回,我不想重复代码。
当然,这完全是理论上的,不适合生产目的。
修改2
Lucian Wischik发现了一篇很棒的文章: Why must async return Task
答案 0 :(得分:13)
三个问题:
仅因为T
是“Task
或派生类型”并不意味着它是Task
或Task<T>
。如果我致电MyMethodAsync<MyCustomTask>
MyCustomTask
来自Task
,那么您会期待什么?
编译器在编译方法时需要知道它是否正在构建一个返回Task
或Task<T>
的状态机 - 它在不同情况下使用不同的辅助类
如果异步方法的返回类型为Task
,则任何return
语句都不能指定值;如果它的返回类型为Task<T>
,则任何return
语句都必须指定一个可隐式转换为T
的值。如何在MyMethodAsync
内工作?这有点像说“我的方法是void
或返回T
- 您可以决定何时调用它”。
目前尚不清楚你在这里想要达到的目标,但基本上这不会起作用。
答案 1 :(得分:-1)
我无法想到MyMethodAsync
的有效定义,它允许它返回从T
派生的通用Task
,而不知道在编译时该类型是什么或采用参数某种。
如果您确实要返回Task
或Task<T>
,那么您可以更新签名以反映这一事实并避免此问题。
如果你真的需要从Task
派生的某种类型,那么你需要重写你的逻辑而不是返回Task
或Task<T>
并包围其他类型。假设这是不可接受的,您将需要删除async
并自己处理状态机。