[英]Why the compiler-generated state machine restores repeatedly the state to -1?
我试图了解迭代器如何在内部工作,以减轻我对线程安全的一些担忧。 让我们考虑例如以下简单的迭代器:
using System.Collections.Generic;
public class MyClass
{
public static IEnumerable<int> MyMethod()
{
yield return 10;
yield return 20;
yield return 30;
}
}
在将此代码复制粘贴到SharpLab.io后,我可以看到在幕后创建的编译器生成的 state 机器。 它是实现接口IEnumerable<int>
和IEnumerator<int>
的 class ,并包含以下MoveNext
方法:
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = 10;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = 20;
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
<>2__current = 30;
<>1__state = 3;
return true;
case 3:
<>1__state = -1;
return false;
}
}
标识符<>1__state
和<>2__current
是此 class 的私有字段:
private int <>1__state;
private int <>2__current;
我注意到这段代码中有一个模式。 首先将<>1__state
字段的值恢复为 -1,然后将<>2__current
分配给下一个迭代值,然后将<>1__state
推进到下一个 state。 我的问题是: <>1__state = -1;
的目的是什么? 线? 我编译了这段代码(在痛苦地重命名了所有非法标识符之后)并确认可以注释掉这一行而不影响 class 的功能。 我不相信 C# 编译器团队只是忘记了这段看似毫无目的的代码。 它的存在肯定是有目的的,我想知道这个目的是什么。
关于为什么您需要一个 state 变量并将其设置为 -1 每次输入您的 switch 语句,没有一个明确的答案。 但我可以想到一个你真的需要这个变量的例子。
就像我在评论部分所说的那样,编译器不知道也不关心 <>2__current 做了什么。
下载文件可能是一个长期运行的 web 请求。 它可能是计算的结果,也可能只是您的示例中的 integer 。 但问题就在这里,因为编译器不知道你的代码做了什么,它可能会抛出异常。 让我们看一个例子,如果你省略 _state 变量会发生什么,你会在尝试下载某些东西时遇到异常。
1) MoveNext is called.
2) this.<>2_current = WebRequest.GetFileAsync() throws HttpRequestException.
3) The exception is caught somewhere and the execution of the program is resumed.
4) The caller invokes MoveNext method.
5) this.<>2_current = WebRequest.GetFileAsync() throws HttpRequestException
所以在这种情况下,我们会陷入一个循环,因为只有在成功下载该数据后才会更改 state。
当我们引入 _state 变量时,结果看起来有很大不同。
1) MoveNext is called.
2) this.<>2_current = WebRequest.GetFileAsync() throws HttpRequestException.
3) The exception is caught somewhere and execution of the program is resumed.
4) The caller invokes MoveNext method.
5) Since there’s no switch case for -1, the default block is reached which informs about the end of a sequence.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.