“foreach"循环的幕后发生了什么? [英] What's going on behind the scene of the 'foreach' loop?

查看:31
本文介绍了“foreach"循环的幕后发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我一直在互联网上搜索,但无法找到有关 C# 中 foreach 循环的幕后真实情况的任何答案.

I've been searching the internet and I'm having trouble finding any answers as to what's really going on behind the scenes with the foreach loop in C#.

我知道这个问题与实际编码无关,但它困扰着我.我对 OO 编程特别是接口很陌生.我了解它们是合同,并且我了解 IEnumerableIEnumerator 是如何工作的 - 或者我认为是这样.

I know this question doesn't really pertain to actually coding but its bothering me. I'm pretty new to OO programming and especially interfaces. I understand they are contracts and I understand how IEnumerable and IEnumerator work - or so I think.

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

I've been reading this article on MSDN: IEnumerable Interface

我了解一切是如何设置的.我有点不清楚 Main 循环中 foreach 如何知道遍历 _people 中的所有值.它怎么知道这个?它是如何通过调用 return new PeopleEnum(_people); 来跟踪 Current 的?

I understand how everything is set up. I'm a little unclear though in the Main loop how the foreach knows to itterate through all the values in _people. How does it know this? How does it keep track of Current by just calling return new PeopleEnum(_people);?

编辑:我看不出这是完全重复的.是的,它的理由相似,并且有人问了同样的问题,但我们正在寻找不同的答案或者我想要的答案没有在上一个问题中讨论过.

EDIT: I don't see how this is an exact duplicate. Yes its similar grounds and the same question is being asked but we are looking for different answers or the answer I wanted was not discussed in the previous question.

像 foreach(int i in obj) {...} 这样的 foreach 循环有点等同于

A foreach loop like foreach(int i in obj) {...} kinda equates to

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

... is "kinda" not the answer I'm looking for.

推荐答案

我鼓励您阅读 C# 规范的第 8.8.4 节,其中详细回答了您的问题.为方便起见,请在此处引用:

I encourage you to read section 8.8.4 of the C# specification, which answers your question in detail. Quoting from it here for your convenience:

表单的foreach语句

A foreach statement of the form

foreach (V v in x) embedded-statement

然后扩展为:

{
    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
    }
}

<小时>

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


The types E, C, V and T are the enumerator, collection, loop variable and collection element types deduced by the semantic analyzer; see the spec for details.

就这样吧.foreach"只是编写while"循环的一种更方便的方式,该循环调用 MoveNext 直到 MoveNext 返回 false.

So there you go. A "foreach" is just a more convenient way of writing a "while" loop that calls MoveNext until MoveNext returns false.

一些微妙的事情:

  • 这不必是生成的代码;所需要的只是我们生成产生相同结果的代码.例如,如果您对数组或字符串进行foreach",我们只会生成一个for"循环(或循环,在多维数组的情况下),它为数组或字符串的字符编制索引,而不是取分配枚举器的费用.

  • This need not be the code that is generated; all that is required is that we generate code that produces the same result. For example, if you "foreach" over an array or a string, we just generate a "for" loop (or loops, in the case of multi-d arrays) that indexes the array or the chars of the string, rather than taking on the expense of allocating an enumerator.

如果枚举器是值类型,那么处理代码可能会也可能不会选择在处理之前将枚举器装箱.不要依赖这种方式或另一种方式.(参见 http://blogs.msdn.com/b/ericlippert/archive/2011/03/14/to-box-or-not-to-box-that-is-the-question.aspx 相关问题.)

If the enumerator is of value type then the disposal code might or might not choose to box the enumerator before disposing it. Don't rely on that one way or the other. (See http://blogs.msdn.com/b/ericlippert/archive/2011/03/14/to-box-or-not-to-box-that-is-the-question.aspx for a related issue.)

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

Similarly, if the casts automatically inserted above are determined to be identity conversions then the casts might be elided even if doing so would normally cause a value type to be copied.

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

Future versions of C# are likely to put the declaration of loop variable v inside the while loop body; this will prevent the common "modified closure" bug that is reported about once a day on Stack Overflow. [Update: This change has indeed been implemented in C# 5.]

这篇关于“foreach"循环的幕后发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆