2009-10-27 66 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每次調用該函數。