【问题标题】:C# - Does function get called for each iteration of a foreach loop? [duplicate]C# - foreach 循环的每次迭代都会调用函数吗? [复制]
【发布时间】:2010-03-15 13:47:52
【问题描述】:

可能重复:
How does foreach work when looping through function results?

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

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

private string[] ReturnParts()
{
     // Build up and return an array. 
}

【问题讨论】:

标签: c# syntax


【解决方案1】:

它只会被调用一次。

附:多次调用它没有什么意义。如果您希望每次结果都不同,您会每次都重新调用它。您将如何迭代不断变化的集合?

【讨论】:

  • 也许在您正在寻找字符串中的确切字符并且只关心当前迭代的情况下?
  • 直到上周我也是这么想的(这些方法只调用一次)。这是上下文:我有一个foreach 循环,它使用一个方法作为项目源;该方法从 SQL 查询中获取结果。 当我看到在每个循环中执行的查询时,我感到非常困惑(我在 foreach 声明中的方法指令上有一个断点,同时我打开了一个 SQL Server 分析器)!任何人都可以解释这种行为吗?
【解决方案2】:

您可以通过在函数“ReturnParts”上放置一个断点来自己确定这一点。如果每次迭代都命中多次,那么是的。

【讨论】:

  • 感谢您的建议。这是找出自己问题答案的好方法
【解决方案3】:

它只会被调用一次。

The foreach loop is equivalent to the following code:

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();
}

【讨论】:

    【解决方案4】:

    几周前我想知道 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();
        }
    }
    

    根据@Eric 的评论...

    我用泛型数组扩展了forwhile、'goto' 和foreach。现在for each 语句看起来使用数组的索引器。对象数组和字符串以类似的方式展开。对象将删除在方法调用 Console.WriteLine 之前发生的装箱,Strings 将分别用char itemstring copy... 替换T itemT[] 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;
    }
    

    【讨论】:

    • @gotoTry 是我能想到的最扩展的版本,没有显示编译后的 IL。
    • 做得很好。当然,这只是对实现 IEnumerable 的事物的扩展。 foreach 为数组和字符串生成不同的代码。
    • @Eric:感谢您的反馈。我想要最通用的版本,但我可能会在以后进一步扩展。 (我主要对 goto 版本感兴趣,因为大多数人仍然认为它是“邪恶的”。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多