Подтвердить что ты не робот

Ли LINQ для объектов прекращает обработку Any(), когда условие истинно?

Рассмотрим следующее:

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

Этот класс имеет набор дочерних объектов, которые имеют метод IsValid(). Предположим, что метод IsValid() - это задача с интенсивным процессором. После встречи с первым дочерним объектом, где IsValid() есть false, теоретическая обработка может прекратиться, потому что результат никогда не может стать истинным. Ли LINQ для объектов фактически перестает оценивать после первого IsValid() = false (например, логического И) или он продолжает оценивать все дочерние объекты?

Очевидно, я мог бы просто поместить это в цикл foreach и разбить первый недопустимый результат, но мне было просто интересно, является ли LINQ для объектов достаточно умным, чтобы это сделать.

EDIT: Спасибо за ответы, по какой-то причине я не думал, что это нужно искать на MSDN.

4b9b3361

Ответ 1

Да, да. Как только он находит совпадение, критерии насыщаются. All похож на то, что он проверяет все элементы, но если он не совпадает с ним, он также заканчивается немедленно.

Exists работает таким же образом.

Любые

Перечисление источника прекращается, как только результат может быть определен.

существует

Элементы текущего списка индивидуально передаются делегату Predicate, и обработка прекращается, когда найдено совпадение.

Все

Перечисление источника прекращается, как только результат может быть определен.

и т.д...

Ответ 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,

Перечисление источника прекращается, как только результат может быть определен.

Ответ 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 останавливается, как только элемент коллекции соответствует предикату.