如果编译以下代码:
private async Task<int> M()
{
return await Task.FromResult(0);
}
然后反编译它(我使用 dotPeek)并检查最重要的MoveNext
方法,你会看到bool
在开头附近声明了一个变量;dotPeek 为我选择了“flag”。
bool flag = true;
在这种情况下,您将在启动第一个异步调用后的默认 case 语句中看到该变量的一个后续使用者:
if (!awaiter.IsCompleted)
{
this.\u003C\u003E1__state = 0;
this.\u003C\u003Eu__\u0024awaiter11 = awaiter;
this.\u003C\u003Et__builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, Program.\u003CP\u003Ed__10>(ref awaiter, ref this);
flag = false;
return;
}
我已经尝试了六个比我最初的例子更复杂的例子,它们在退出方法之前只分配给这个变量是一致的。所以换句话说,在我迄今为止尝试过的所有情况下,这个变量不仅不会被消耗,而且只会在从方法返回之前立即被赋予一个非初始值——一个定义上赋值的时间点无用。
作为背景,我很享受尝试通过 C# -> JS 交叉编译器在 Javascript 中实现 async/await 的过程。我试图了解在什么情况下我需要考虑这个标志的效用。从表面上看,它似乎是虚假的,因此我应该忽略它。但是,我想了解为什么 C# 编译器会引入这个变量——我怀疑有更复杂的表达式会以一种有用的方式使用这个变量。
简而言之:为什么 C# 编译器会生成这个flag
变量?