"foreach"循环背后发生了什么?

Ada*_*eck 11 c# clr foreach

可能重复:
foreach循环如何在C#中工作?

我一直在网上搜索,我很难找到任何关于foreachC#循环幕后真实情况的答案.

我知道这个问题并不真正与实际编码有关,但它困扰着我.我对OO编程很熟悉,特别是接口.我知道他们是合同,我知道如何IEnumerableIEnumerator工作-我还是这么认为.

我一直在MSDN上阅读这篇文章: IEnumerable Interface

我理解一切都是如何建立的.我有点不清楚,虽然在Main循环中如何foreach知道通过所有的值来迭代_people.怎么知道这个?它如何Current通过调用来跟踪return new PeopleEnum(_people);

编辑:我不知道这是一个完全重复.是的,它的类似理由和同样的问题被问到,但我们正在寻找不同的答案我想要的答案在前一个问题中没有讨论过.

像foreach(在obj中的int i){...}等等的foreach循环等同于

......"有点"不是我正在寻找的答案.

Eri*_*ert 22

我建议您阅读C#规范的第8.8.4节,它会详细回答您的问题.为方便起见,请在此处引用:


表格的foreach声明

foreach (V v in x) embedded-statement
Run Code Online (Sandbox Code Playgroud)

然后扩展到:

{
    E e = ((C)(x)).GetEnumerator();
    try 
    {
        V v;
        while (e.MoveNext()) 
        {
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally 
    {
         code to Dispose e if necessary
    }
}
Run Code Online (Sandbox Code Playgroud)

E,C,V和T类型是语义分析器推导出的枚举器,集合,循环变量和集合元素类型; 请参阅规格了解详情.

你去吧 "foreach"只是编写调用MoveNext的"while"循环的一种更方便的方法,直到MoveNext返回false.

一些微妙的事情:

  • 这不一定是生成的代码; 所需要的只是我们生成产生相同结果的代码.例如,如果你在一个数组或一个字符串上"foreach",我们只生成一个"for"循环(或多循环,在多d数组的情况下)索引数组或字符串的字符,而不是采取以分配一个枚举器为代价.

  • 如果枚举数是值类型,则处置代码可能会也可能不会选择在处理枚举器之前对其进行封装.不要依赖那种方式.(有关相关问题,请参阅http://blogs.msdn.com/b/ericlippert/archive/2011/03/14/to-box-or-not-to-box-that-is-the-question.aspx. )

  • 类似地,如果上面自动插入的强制转换被确定为身份转换,那么即使这样做通常会导致复制值类型,也可能省略强制转换.

  • C#的未来版本很可能将循环变量的声明v 放在 while循环体中; 这将防止在Stack Overflow上每天报告一次的常见"修改后的闭包"错误.[ 更新: 此更改确实已在C#5中实现.]