2009-10-27 38 views
28

假设我有以下代码:循环遍历函数结果时foreach如何工作?

foreach(string str in someObj.GetMyStrings()) 
{ 
    // do some stuff 
} 

someObj.GetMyStrings()可以在循环的每次迭代叫什么名字?代之以做更好:

List<string> myStrings = someObj.GetMyStrings(); 
foreach(string str in myStrings) 
{ 
    // do some stuff 
} 

+20

试试看看 - 在'GetMyStrings()'中放置一个断点,看看调试器在那里停了多少次! – AakashM 2009-10-27 18:38:24

回答

45

该函数只调用一次,返回一个IEnumerator<T>;在那之后,用于通过结果来迭代该MoveNext()方法和Current属性:

foreach (Foo f in GetFoos()) 
{ 
    // Do stuff 
} 

是有点相当于:

using (IEnumerator<Foo> iterator = GetFoos().GetEnumerator()) 
{ 
    while (iterator.MoveNext()) 
    { 
     Foo f = iterator.Current; 
     // Do stuff 
    } 
} 

注意,迭代器设置在所述端部 - 这是特别从迭代器块配置资源,重要的如:

public IEnumerable<string> GetLines(string file) 
{ 
    using (TextReader reader = File.OpenText(file)) 
    { 
     string line; 
     while ((line = reader.ReadLine()) != null) 
     { 
      yield return line; 
     } 
    } 
} 

在上面的代码,你真的想要的文件被关闭WH在完成迭代之后,编译器巧妙地执行IDisposable以完成这项工作。

+1

+1用于Dispose讨论。好东西。 – 2009-10-27 19:29:03

+0

纠正我,如果我错了,但我认为C#编译器不允许您在foreach循环运行时编辑IEnumerable。 – 2016-08-26 06:37:54

+0

@ShaswatRungta:我不知道你的意思是“编辑IEnumerable”,或者这与这个问题有关。 – 2016-08-26 06:43:26

18

否..该函数将被调用一次以获取IEnumerable ..然后会重复调用MoveNext和Current。

3

GetMyStrings()回调IEnumerable类型的对象。运行时知道如何处理。它调用IEnumerable.GetEnumerator(),然后调用MoveNext()和Current。

0

只是为了圆满的问题,以防万一你陷入了“所有的人都是一样的”; for(int x = 0; x < ProvideCeiling(); x ++) does每次调用该函数。