C# 为什么编译器生成的状态机会反复将状态恢复为-1?

C# 为什么编译器生成的状态机会反复将状态恢复为-1?,c#,compilation,iterator,state-machine,C#,Compilation,Iterator,State Machine,我试图理解迭代器是如何在内部工作的,以减轻我对线程安全的一些担忧。让我们考虑下面的例子 简单迭代器: using System.Collections.Generic; public class MyClass { public static IEnumerable<int> MyMethod() { yield return 10; yield return 20; yield return 30; } }

我试图理解迭代器是如何在内部工作的,以减轻我对线程安全的一些担忧。让我们考虑下面的例子 简单迭代器:

using System.Collections.Generic;

public class MyClass
{
    public static IEnumerable<int> MyMethod()
    {
        yield return 10;
        yield return 20;
        yield return 30;
    }
}
标识符1__state和2__current是此类的专用字段:

private int <>1__state;
private int <>2__current;

我注意到这段代码中有一个模式。首先,1__状态字段的值恢复为-1,然后将2__当前值分配给下一个迭代值,然后将1__状态前进到下一个状态。我的问题是:1__状态=-1的目的是什么;线我在痛苦地重命名了所有非法标识符之后编译了这段代码,并确认这一行可以注释掉,而不会影响类的功能。我不相信C编译器团队忘记了这段看似毫无目的的代码。当然,它的存在肯定有其目的,我想知道它的目的是什么。

对于为什么需要状态变量并在每次输入switch语句时将其设置为-1,没有一个明确的答案。但是我可以想到一个例子,在这里你真的需要变量

正如我在评论部分所说,编译器不知道,也不关心2__;u current做什么

下载文件可能是一个长期运行的web请求。它可能是计算的结果,也可能只是一个整数,如您的示例所示。但问题就在这里,因为编译器不知道您的代码是做什么的,所以它可能会抛出异常。让我们看一个例子,如果您省略了_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变量时,结果看起来大不相同

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.

这是什么?@OlivierRogier这是一个前缀,似乎对编译器生成的代码有效。根据C规范,它肯定是无效的,所以我不得不重命名变量来编译这段代码。我不明白,因为是菱形运算符:它允许在开放类型上使用真正的泛型多态性,但在C中还不可用,正如我所知,@OlivierRogier我认为尖括号在这里没有任何意义。可能是为了使标识符无效而添加的,以避免和用户代码冲突;这相当容易。这就是状态机的工作原理。因为状态机不知道您正在请求什么值,并且您的用户代码可能是一个非常慢的webservice请求,所以它将状态设置为-1,表示我正忙于获取下一个值。有趣。因此,此赋值的目的是禁止重用遇到异常的枚举数。我想知道是否所有枚举数的行为都是相同的,例如LINQ枚举数,或者只是编译器生成的枚举数。我的测试显示了行为上的差异。我提出了一个新问题。
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.