【问题标题】:When does IEnumerable.Any(Func) return a value?IEnumerable.Any(Func) 什么时候返回值?
【发布时间】:2012-08-23 21:40:43
【问题描述】:

我最近在我使用的代码库中看到了一些代码,ReSharper 提出将其重构为 collection.Any(Func< bool >)

我想知道这对性能的影响。假设我有一个看起来像这样的电话:

bool hasEvenValue = collection.Any(i => (i % 2) == 0);

...还有看起来像这样的数据...

{ 1, 2, 3, 5, 3, 5, 1, 3, 5, 2 }

Enumerable.Any() 什么时候返回值?第二个数据元素,或者在这种情况下,它会在返回 true 之前处理每个元素吗?

【问题讨论】:

    标签: c# performance linq lambda ienumerable


    【解决方案1】:

    它一看到匹配的元素就返回,如果没有,它会处理整个序列。

    因此,它比使用.Count(...) != 0 更好(也更具可读性和语义意义)。

    【讨论】:

    • 一次返回一个吗?它可以返回块吗?
    • .Any 返回一个布尔值——真或假,数据集是否有满足条件的元素。要在 LINQ 中返回块,最好使用 .Select(),但这超出了本主题的范围。
    【解决方案2】:

    这是IEnumerable<T>.Any(...)的实现(未使用dotKeep编译):

    public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
      if (source == null)
        throw Error.ArgumentNull("source");
      if (predicate == null)
        throw Error.ArgumentNull("predicate");
      foreach (TSource source1 in source)
      {
        if (predicate(source1))
          return true;
      }
      return false;
    }
    

    所以基本上只要项目满足条件,它就会返回。

    【讨论】:

      【解决方案3】:

      IEnumerable.Any(Func) 什么时候返回值?

      总是在它被执行时立即立即执行,因为它没有被延迟执行。它返回一个布尔值,指示序列中的 一个元素 是否为给定谓词返回 true。因此它不需要像Count 那样执行整个查询。

      【讨论】:

        【解决方案4】:

        这是我在 LINQPad 中编写的一些代码,用于说明 Any 运算符在第一次匹配后终止。

        void Main()
        {
            Console.WriteLine("Are there any evens? " + YieldEvenThenThrowEnumerable().Any(i => i % 2 == 0));
            Console.WriteLine("still running");
            Console.WriteLine("Are there any odds? " + YieldEvenThenThrowEnumerable().Any(i => i % 2 == 1));
            Console.WriteLine("never reaches this point");
        }
        
        IEnumerable<int> YieldEvenThenThrowEnumerable()
        {
            yield return 2;
            throw new InvalidOperationException("TEST");
        }
        

        哪些输出:

        有没有偶数?
        真的
        仍在运行
        &LT;此时从 enumerable 中抛出 InvalidOperationException &GT;

        如果测试“如果有偶数”的第一个 Any 调用遍历了整个可枚举,则程序将终止而不显示任何消息。第二次调用是为了说明“如果有奇数”测试遍历整个列表,从而引发异常。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-25
          • 2021-12-22
          • 2014-11-04
          • 1970-01-01
          • 2021-10-11
          • 2016-09-05
          • 2015-03-15
          相关资源
          最近更新 更多