IEnumerable.Any比带有中断的for循环快吗?

| 我们在打开表单的代码中遇到了一些缓慢,这可能是由于带有
break
for
循环需要花费很长时间来执行。我将其切换为
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;
}
新实施:
public bool ContainsProduct(int productID) {
    return this.ProductIDs.Any(t => productID == t);
}
    
已邀请:
        第一个实现要快一些(枚举比
for
循环要慢一些)。第二个更具可读性。 更新 奥德的答案可能是正确的,而且在发现它时做得很好。第一个比较慢,因为它涉及数据库往返。否则,它会比我说的快一点。 更新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();
    }
输出如下:   循环耗时12198      迭代花费20922 因此循环是迭代/枚举的两倍。     
        称其为有根据的猜测:
this.ProductIDs.Length
这可能就是缓慢之处所在。如果每次迭代都从数据库中检索“ 3”的列表以获取“ 10”,那的确会非常慢。您可以通过对应用程序进行概要分析来确认这一点。 如果不是这种情况(例如,内存中有“ 3”,并且已缓存了“ 10”),则两者的运行时间应该几乎相同。     
        我认为它们或多或少是相同的。我通常参考Jon Skeet的“重新实现LINQ to Objects”博客系列,以了解扩展方法的工作原理。这是
Any()
All()
的帖子 这是该帖子中实施
Any()
的核心部分
public static bool Any<TSource>( 
    this IEnumerable<TSource> source, 
    Func<TSource, bool> predicate) 
{ 
   ...

    foreach (TSource item in source) 
    { 
        if (predicate(item)) 
        { 
            return true; 
        } 
    } 
    return false; 
} 
    
        这篇文章假设
ProductIDs
List<T>
或数组。所以我在谈论Linq-to-objects。 与传统的基于循环的代码相比,Linq通常更慢,但更短/更易读。典型的是2-3倍,具体取决于您的工作。 您可以重构代码以使
this.ProductIDs
变成
HashSet<T>
吗?或者至少对数组排序,以便可以使用二进制搜索。您的问题是您正在执行线性搜索,如果有很多产品,这会很慢。     
        我认为下面的实现会比相应的linq实现快一点,但是虽然很小
public bool ContainsProduct(int productID) {
    var length = this.ProductIDs.Length;

    for (int i = 0; i < length; i++) {
        if (productID == this.ProductIDs[i]) {
            return true;
        }
    }

    return false;
}
    
        区别通常是内存使用率和速度。 但是通常,当您知道将要使用数组的所有元素时,应该使用for循环,而在其他情况下,则应尝试使用while或do while。 我认为此解决方案使用最少的资源
int i = this.ProductIDs.Length - 1;

while(i >= 0) {
 if(this.ProductIDs[i--] == productId) {
   return true;
 }
}

return false;
    

要回复问题请先登录注册