C# – 是否为foreach循环的每次迭代调用函数?

可能重复:
在遍历函数结果时,foreach如何工作?

如果我具有以下function – 将在foreach循环中为每次迭代调用ReturnParts(),还是只调用一次?

private void PrintParts() { foreach(string part in ReturnParts()) { // Do Something or other. } } private string[] ReturnParts() { // Build up and return an array. } 

它只会被调用一次。

PS多次调用它没有多大意义。 如果您希望每次结果不同,您可以每次重新调用它。 你将如何迭代不断变化的集合?

你可以通过在函数“ReturnParts”上放置一个断点来自己确定它。如果它每次迭代都达到多次,那么肯定是。

它只会被调用一次。

foreach循环等效于以下代码:

 IEnumerable enumerator = (collection).GetEnumerator(); try { while (enumerator.MoveNext()) { string part = (string)enumerator.Current; // Do Something or other. } } finally { IDisposable disposable = enumerator as System.IDisposable; if (disposable != null) disposable.Dispose(); } 

想知道几周前for,foreach,while和goto之间的差异所以我写了这个测试代码。 所有方法都将编译到相同的IL中(除了foreach版本上的变量名之外)。在调试模式下,一些NOP语句将处于不同的位置。

 static void @for(IEnumerable input) { T item; using (var e = input.GetEnumerator()) for (; e.MoveNext(); ) { item = e.Current; Console.WriteLine(item); } } static void @foreach(IEnumerable input) { foreach (var item in input) Console.WriteLine(item); } static void @while(IEnumerable input) { T item; using (var e = input.GetEnumerator()) while (e.MoveNext()) { item = e.Current; Console.WriteLine(item); } } static void @goto(IEnumerable input) { T item; using (var e = input.GetEnumerator()) { goto check; top: item = e.Current; Console.WriteLine(item); check: if (e.MoveNext()) goto top; } } static void @gotoTry(IEnumerable input) { T item; var e = input.GetEnumerator(); try { goto check; top: item = e.Current; Console.WriteLine(item); check: if (e.MoveNext()) goto top; } finally { if (e != null) e.Dispose(); } } 

Per @ Eric的评论……

我已经扩展forwhile ,’goto’和foreach使用generics数组。 现在for each语句看起来使用数组的索引器。 对象数组和字符串以类似的方式扩展。 对象将删除在方法调用Console.WriteLine之前发生的装箱,并且Strings将分别用char itemstring copy...替换T itemT[] copy... 请注意,不再需要临界区,因为不再使用一次性枚举器。

 static void @for(T[] input) { T item; T[] copy = input; for (int i = 0; i < copy.Length; i++) { item = copy[i]; Console.WriteLine(item); } } static void @foreach(T[] input) { foreach (var item in input) Console.WriteLine(item); } static void @while(T[] input) { T item; T[] copy = input; int i = 0; while (i < copy.Length) { item = copy[i]; Console.WriteLine(item); i++; } } static void @goto(T[] input) { T item; T[] copy = input; int i = 0; goto check; top: item = copy[i]; Console.WriteLine(item); i++; check: if (i < copy.Length) goto top; }