2009-10-27 10 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()'にブレークポイントを置き、デバッガがそこで停止する回数を確認してください! Disposeディスカッションのために+1 – AakashM

答えて

45

この関数は1回だけ呼び出され、IEnumerator<T>を返します。その後、MoveNext()方法及びCurrent性は結果を反復するために使用される:反復子が端部に配置されていることを

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

注 - これは特にある:

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

は幾分等価です

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

上記のコードでは、ファイルを本当に閉じたいと思っていますコンパイラは反復処理を完了し、コンパイラはその作業を巧みに行うためにIDisposableを実装します。

+1

+1いい物。 –

+0

私が間違っている場合は私を修正します。しかし、foreachループが実行されている間はC#コンパイラでIEnumerableを編集することはできません。 –

+0

@ShaswatRungta:「IEnumerableを編集する」という意味、またはこれがどのように問題に関連しているかわかりません。 –

18

いいえ.. IEnumerableを取得するために関数が一度呼び出されます。その後、MoveNextとCurrentを繰り返し呼び出します。

3

GetMyStrings()は、IEnumerable型のオブジェクトを返します。ランタイムはそれに対処する方法を知っています。 IEnumerable.GetEnumerator()を呼び出し、その列挙子オブジェクトでMoveNext()とCurrentを呼び出します。

0

あなたが「すべてのものは同じです」に該当する場合は、質問を丸めるだけです。 for(int x = 0; x < ProvideCeiling(); x ++) は毎回その関数を呼び出します。

関連する問題