【发布时间】:2021-06-30 22:20:22
【问题描述】:
考虑以下示例代码
public static class TestClass
{
static async TaskWrapper<int> Test()
{
var task = Task.FromResult(4);
return await new TaskWrapper<int>(task);
}
}
public class TaskWrapper<T>
{
private readonly Task<T> _thing;
public TaskAwaiter<T> GetAwaiter() => _thing.GetAwaiter();
public TaskWrapper(Task<T> thing)
{
_thing = thing;
}
}
编译器在Test()函数上报如下错误:error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>。
为什么会这样? TaskWrapper 类型通过推迟到包装的任务类型来实现 GetAwaiter() 方法。事实上,下面的测试函数编译得很好,证明TaskWrapper确实是可以等待的:
static async Task Test()
{
var task = Task.FromResult(4);
_ = await new TaskWrapper<int>(task);
}
【问题讨论】:
-
错误信息对我来说似乎非常清楚。解释见副本。这与您的
TaskWrapper<T>类型有什么关系尚不清楚;错误消息特别与使用async关键字的方法声明有关。这并不意味着该语言中没有其他“可等待”结构。错误信息没有不一致的地方。 -
我喜欢有人关闭这个问题的事实,因为据称它在另一个问题中得到了回答——它本身被关闭是因为据说太模糊而无法回答。 (感觉就像一部等待编写的xkcd卡通片)更相关的是,另一个问题不涉及“类似任务的类型”。这个很明显。那么究竟什么是类任务类型呢?我也想知道答案。但是你显然不会在这里得到答案。也许试试github.com/dotnet/csharplang。
-
如果您只是想创建一个可等待的内容,请参阅 Stephen Toubs 博客 devblogs.microsoft.com/pfxteam/await-anything
-
TLDR;等待!=任务之类的。您可以等待您的 TaskWrapper,因为
GetAwaiter()符合 docs.microsoft.com/en-us/dotnet/csharp/language-reference/…。像类型这样的任务必须有一个构建器,以便编译器/运行时可以构造您的任务并返回它。 -
Tasklike 极为罕见,尤其是现在我们有
ValueTask<T>。你到底想用TaskWrapper<T>做什么?
标签: c# async-await