【问题标题】:Does LINQ to objects stop processing Any() when condition is true?当条件为真时,LINQ to objects 是否停止处理 Any()?
【发布时间】:2011-03-21 17:49:19
【问题描述】:

考虑以下几点:

bool invalidChildren = this.Children.Any(c => !c.IsValid());

这个类有一个具有IsValid() 方法的子对象集合。假设IsValid() 方法是一个处理器密集型任务。在遇到IsValid()false 的第一个子对象后,理论上可以停止处理,因为结果永远不会为真。 LINQ to 对象实际上在第一个 IsValid() = false 之后停止评估(如逻辑 AND)还是继续评估所有子对象?

显然我可以把它放在一个 foreach 循环中并在第一个无效结果上中断,但我只是想知道 LINQ to objects 是否也足够聪明地做到这一点。

编辑: 感谢您的回答,出于某种原因,我没有想到自己在 MSDN 上查找它。

【问题讨论】:

    标签: c# linq-to-objects


    【解决方案1】:

    是的。一旦找到匹配项,就满足条件。 All 的相似之处在于它会检查所有项目,但如果其中一项不匹配,它也会立即结束。

    Exists 也以同样的方式工作。

    Any

    只要可以确定结果,就停止对源的枚举。

    Exists

    当前 List 的元素单独传递给 Predicate 委托,并在找到匹配项时停止处理。

    All

    只要可以确定结果,就停止对源的枚举。

    等等……

    【讨论】:

      【解决方案2】:

      是的,一旦可以评估结果,它就会停止。这是一个快速的证明:

      class Program
          {
              static void Main(string[] args)
              {
                  bool allvalid = TestClasses().Any(t => !t.IsValid());
                  Console.ReadLine();
              }
      
              public static IEnumerable<TestClass> TestClasses()
              {
                  yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}",Environment.NewLine)); return true; } };
                  yield return new TestClass() { IsValid = () => { Console.Write(string.Format("FALSE{0}", Environment.NewLine)); return false; } };
                  yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
                  yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
              }
          }
      
          public class TestClass
          {
              public Func<bool> IsValid {get;set;}
          }
      

      【讨论】:

        【解决方案3】:

        是的,它会在遇到条件匹配的第一个项目后停止,在您的情况下,c.IsValid() 返回false 的第一个项目。

        来自MSDN

        源的枚举停止 只要结果可以 确定。

        【讨论】:

          【解决方案4】:

          根据MSDN

          source的枚举一有结果就停止。

          【讨论】:

            【解决方案5】:

            这是一个快速而肮脏的经验测试,您可以自己看看:

            class Kebab
            {
                public static int NumberOfCallsToIsValid = 0;
            
                public bool IsValid()
                {
                    NumberOfCallsToIsValid++;
                    return false;
                }
            }
            
            ...
            
            var kebabs = new Kebab[] { new Kebab(), new Kebab() };
            kebabs.Any(kebab => !kebab.IsValid());
            
            Debug.Assert(Kebab.NumberOfCallsToIsValid == 1);
            

            结果是,是的,只要集合项与谓词匹配,Any LINQ 运算符就会停止。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-08
              • 1970-01-01
              • 1970-01-01
              • 2018-03-03
              相关资源
              最近更新 更多