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

Rob*_*t W 26 c# syntax

可能重复:
循环功能结果时foreach如何工作?

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

private void PrintParts()
{
     foreach(string part in ReturnParts())
     {
         // Do Something or other. 
     }
}

private string[] ReturnParts()
{
     // Build up and return an array. 
}
Run Code Online (Sandbox Code Playgroud)

小智 32

它只会被调用一次.

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


Ach*_*les 19

您可以通过在函数"ReturnParts"上放置一个断点来自行确定.如果每次迭代都会遇到多个时间,那么是的.


SLa*_*aks 11

它只会被调用一次.

foreach循环等效于以下代码:

IEnumerable<string> 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();
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*ted 7

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

static void @for<T>(IEnumerable<T> input)
{
    T item;
    using (var e = input.GetEnumerator())
        for (; e.MoveNext(); )
        {
            item = e.Current;
            Console.WriteLine(item);
        }
}
static void @foreach<T>(IEnumerable<T> input)
{
    foreach (var item in input)
        Console.WriteLine(item);
}
static void @while<T>(IEnumerable<T> input)
{
    T item;
    using (var e = input.GetEnumerator())
        while (e.MoveNext())
        {
            item = e.Current;
            Console.WriteLine(item);
        }
}
static void @goto<T>(IEnumerable<T> 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<T>(IEnumerable<T> 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Per @ Eric的评论......

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

static void @for<T>(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>(T[] input)
{
    foreach (var item in input)
        Console.WriteLine(item);
}
static void @while<T>(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>(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;
}
Run Code Online (Sandbox Code Playgroud)

  • 做得很好.当然,这只是实现IEnumerable <T>的扩展.foreach为数组和字符串生成不同的代码. (2认同)