说我有这样的方法:
private async Task SomeMethod()
{
await DoSomethingAsync();
await DoSomethingElseAsync();
return;
}
鉴于DoSomethingElseAsync
返回Task
,您似乎应该可以执行此操作:
private async Task SomeMethod()
{
await DoSomethingAsync();
return DoSomethingElseAsync();
}
但是编译器抱怨这个:
自'
SomeMethod
'是一个返回'Task
&#39;的异步方法,返回关键字后面不能跟一个对象表达式。您打算退回&#39;Task<T>
&#39;?
为什么?
答案 0 :(得分:5)
与yield return
和return
的工作原理非常相似。对于迭代器,您可以使用这些方法之一
public IEnumerable<int> SomeIterator()
{
for(int I = 0; I < 10; I++) yield return I;
}
public IEnumerable<int> SomeIterator()
{
return Enumerable.Range(0, 10); // return result of another iterator.
}
但是你不能同时拥有这两个。它不起作用,因为迭代器要么被编译器转换为类来处理使用yield
的延迟迭代,要么就像其他返回其他东西的常规方法一样。
public IEnumerable<int> SomeIterator() // not valid
{
for(int I = 0; I < 10; I++) yield return I;
return Enumerable.Range(0, 10);
}
return
和async/await
的情况相同。对于返回类型为Task
的方法,您可以返回Task
或使用async/await
。
对于Task<T>
如果使用await,则必须返回T
,但不能返回Task<T>
,因为该方法已编译到状态机,然后方法必须返回T
。 (对于Task
方法无效)
如果您不使用async/await
方法,则与其他常规方法完全相同。
答案 1 :(得分:0)
使用await
时 - 控制流可能会保留当前方法并返回给调用者。假设DoSomethingAsync
是一些长时间运行的操作。你打电话给SomeMethod
。 DoSomethingAsync
任务已启动,但您无法等待它在该方法内完成 - 否则将无法执行任何&#34; async&#34;。因此控制流离开Method
并应向调用者提供返回值。返回值是在完成整个SomeMethod
时完成的任务。它可以在有或没有结果的情况下完成(Task
或Task<T>
返回值)。因此,await
之后返回的内容不能是SomeMethod
的返回类型 - 它只能是结果类型T
(如果SomeMethod
返回任务)或只是简单{{如果return
返回简单SomeMethod
,则表示Task
已完成。
答案 2 :(得分:0)
在常规方法中,return
表示&#34;从方法&#34;中返回此值(如果有)。在async
方法中,return
的含义更改为&#34;将返回的Task
的结果设置为此值(如果有)&#34;。
但是你不能将两者结合起来:在async Task
方法中,你不能直接return
一个Task
。这样做的一个原因是,如果您await
编辑,该方法实际上已经返回Task
,并且无法返回另一个。
在返回时,async Task
方法的行为类似于void
方法,因为它只允许return;
,但绝不允许return value;
。