有谁知道为什么异步方法不允许有 ref 和 out 参数?
当然。想一想 - 一个异步方法通常返回 几乎立即,远在大多数实际逻辑执行之前......这是异步完成的。因此,任何out 参数都必须在第一个await 表达式之前分配,并且很可能必须对ref 参数进行一些限制,以阻止它们在第一个await 表达式之后使用,因为在那之后它们甚至可能无效。
考虑使用out 和ref 参数调用异步方法,并使用局部变量作为参数:
int x;
int y = 10;
FooAsync(out x, ref y);
FooAsync 返回后,方法本身可以返回 - 因此这些局部变量在逻辑上将不再存在......但异步方法仍然可以有效地在其延续中使用它们。大问题。编译器可以创建一个新类来以与 lambda 表达式相同的方式捕获变量,但这会导致其他问题......当延续在不同的线程上运行时,通过方法的任意点。至少可以说很奇怪。
基本上,由于涉及时间问题,对async 方法使用out 和ref 参数是没有意义的。请改用包含您感兴趣的所有数据的返回类型。
如果您只对在第一个 await 表达式之前更改的 out 和 ref 参数感兴趣,则始终可以将方法一分为二:
public Task<string> FooAsync(out int x, ref int y)
{
// Assign a value to x here, maybe change y
return FooAsyncImpl(x, y);
}
private async Task<string> FooAsyncImpl(int x, int y) // Not ref or out!
{
}
编辑:使用Task<T> 使用out 参数并像返回值一样直接在方法内分配值是可行的。不过这有点奇怪,而且它不适用于ref 参数。