IEnumerable.Any比休息的for循环快吗?

Ian*_*ien 5 c# performance ienumerable loops

我们在打开表单的代码中经历了一些缓慢,这可能是由于for循环break执行需要很长时间.我把它换成了一个IEnumerable.Any(),很快看到表格打开了.我现在正在试图弄清楚是否单独进行此更改会提高性能,还是ProductIDs更有效地访问该属性.这种实施应该更快,如果是这样,为什么?

原始实施:

public bool ContainsProduct(int productID) {
    bool containsProduct = false;
    for (int i = 0; i < this.ProductIDs.Length; i++) {
        if (productID == this.ProductIDs[i]) {
            containsProduct = true;
            break;
        }
    }
    return containsProduct;
}
Run Code Online (Sandbox Code Playgroud)

新实施:

public bool ContainsProduct(int productID) {
    return this.ProductIDs.Any(t => productID == t);
}
Run Code Online (Sandbox Code Playgroud)

Ode*_*ded 9

称之为有根据的猜测:

this.ProductIDs.Length
Run Code Online (Sandbox Code Playgroud)

这可能是缓慢所在的地方.如果ProductIDs在每次迭代中从数据库(例如)中检索到的列表以便获得Length它将确实非常慢.您可以通过分析您的应用程序来确认这一点.

如果不是这种情况(例如ProductIDs在内存中并且Length被缓存),那么两者应该具有几乎相同的运行时间.


Ali*_*tad 8

第一个实现稍快(枚举比for循环稍慢).第二个是更具可读性.


UPDATE

Oded的回答可能是正确的,并且很好地发现它.第一个在这里较慢,因为它涉及数据库往返.否则,就像我说的那样稍快.


更新2 - 证明

这是一个简单的代码,显示为什么第一个更快:

    public static void Main()
    {

        int[] values = Enumerable.Range(0, 1000000).ToArray();

        int dummy = 0;
        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();
        for (int i = 0; i < values.Length; i++)
        {
            dummy *= i;
        }
        stopwatch.Stop();
        Console.WriteLine("Loop took {0}", stopwatch.ElapsedTicks);

        dummy = 0;
        stopwatch.Reset();
        stopwatch.Start();
        foreach (var value in values)
        {
            dummy *= value;         
        }
        stopwatch.Stop();
        Console.WriteLine("Iteration took {0}", stopwatch.ElapsedTicks);

        Console.Read();
    }
Run Code Online (Sandbox Code Playgroud)

这是输出:

Loop花了12198

迭代耗时20922

所以循环是迭代/枚举的两倍快.

  • 我认为你所指的*略微*对于优化来说是荒谬的. (2认同)