当条件为真时,LINQ to对象是否停止处理Any()?

时间:2011-03-21 17:49:19

标签: c# linq-to-objects

请考虑以下事项:

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

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

显然我可以把它放在一个foreach循环中并打破第一个无效结果,但我只是想知道对象的LINQ是否足够聪明来做到这一点。

修改 感谢您的回答,出于某种原因,我不想在MSDN上查找它。

5 个答案:

答案 0 :(得分:21)

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

Exists也以同样的方式运作。

Any

  

一旦确定结果,就会停止源的枚举。

Exists

  

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

All

  

一旦确定结果,就会停止源的枚举。

等...

答案 1 :(得分:6)

是的,只要评估结果就会停止。这是一个快速证明:

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;}
    }

答案 2 :(得分:2)

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

来自MSDN

  

停止源的枚举   一旦结果可以   确定。

答案 3 :(得分:1)

根据MSDN

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

答案 4 :(得分:1)

这是一个快速而肮脏的实证测试,可以自己看看:

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运算符会在集合项与谓词匹配时立即停止。