Ли LINQ для объектов прекращает обработку Any(), когда условие истинно?
Рассмотрим следующее:
bool invalidChildren = this.Children.Any(c => !c.IsValid());
Этот класс имеет набор дочерних объектов, которые имеют метод IsValid()
. Предположим, что метод IsValid()
- это задача с интенсивным процессором. После встречи с первым дочерним объектом, где IsValid()
есть false
, теоретическая обработка может прекратиться, потому что результат никогда не может стать истинным. Ли LINQ для объектов фактически перестает оценивать после первого IsValid() = false
(например, логического И) или он продолжает оценивать все дочерние объекты?
Очевидно, я мог бы просто поместить это в цикл foreach и разбить первый недопустимый результат, но мне было просто интересно, является ли LINQ для объектов достаточно умным, чтобы это сделать.
EDIT:
Спасибо за ответы, по какой-то причине я не думал, что это нужно искать на MSDN.
Ответы
Ответ 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 останавливается, как только элемент коллекции соответствует предикату.