【问题标题】:Method execution inside loop declaration循环声明内的方法执行
【发布时间】:2011-07-06 12:08:56
【问题描述】:

我正在查看我正在开发的网站的性能,并且发现了一些我编写的代码:

 foreach (WorkItem wi in p.getWorkItems(dateFrom, dateTo))
 {
     someFunction(wi);
 }

在上面的代码中,p.getWorkItems 方法是否在每次循环执行时都运行?或者它是否执行一次,将结果对象保存在内存中,然后只增加指向它正在使用的对象的指针?原因是getWorkItems 在幕后做了很多事情(比较、排序、其他查询),所以最好不要一遍又一遍地执行。如果是这种情况,那么我最好按照以下方式进行:

 List<WorkItem> workload = p.getWorkItems(dateFrom, dateTo);

 for (int i = 0; i < workload.Count; i++)
 {
     someFunction(workload[i]);
 }

它是用 C# 编写的,但我假设答案将适用于大多数类似的语言..

【问题讨论】:

  • 如果p.getWorkItems每次都执行,那么in如何迭代结果?

标签: c# performance optimization loops


【解决方案1】:

您应该了解如何将foreach 循环转换为 C# 代码。从 C# 语言规范的 8.8.4 开始,您的循环

foreach (WorkItem wi in p.getWorkItems(dateFrom, dateTo)) {
   someFunction(wi);
}

变成

var enumerator = p.getWorkItems(dateFrom, dateTo).GetEnumerator();
try {
    WorkItem wi;
    while(enumerator.MoveNext()) {
        wi = (WorkItem)enumerator.Current;
        someFunction(wi);
    }
}
finally {
    IDisposable disposable = enumerator as System.IDisposable;
    if (disposable != null) disposable.Dispose();
}

因此,很明显p.getWorkItems 只执行一次。

【讨论】:

    【解决方案2】:

    还是执行一次,将结果对象保存在内存中,然后只增加指向它正在使用的对象的指针?

    是的。(*) 您可以通过在getWorkItems 中添加打印声明来证明这一点。

    (*) 除非结果对象递归调用getWorkItems

    【讨论】:

      【解决方案3】:

      p.getWorkItems 只被调用一次。结果存储在内存中,foreach 循环迭代内存中的结果对象。

      如果不是这样,那么每次方法都会返回新的列表,foreach 永远不会结束。

      【讨论】:

        【解决方案4】:

        一个小证明申请:

        using System;
        using System.Collections.Generic;
        
        public class Program
        {
            public static void Main()
            {
                foreach(var i in GetCol()) {
                    Console.WriteLine(i);
                }
            }
        
            private static List<int> GetCol() {
                Console.WriteLine("I have been called");
        
                return new List<int>(){1, 2, 3, 4};
            }
        }
        
        /* Output
        I have been called
        1
        2
        3
        4 */
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-02
          • 1970-01-01
          • 1970-01-01
          • 2018-05-07
          • 1970-01-01
          • 2014-06-15
          相关资源
          最近更新 更多