Страницы

Поиск по вопросам

суббота, 13 октября 2018 г.

Метод `All()` для пустой коллекции возвращает `true`: баг или фича?

У меня есть класс Item
public class Item { public int ParentId {get;set;} public int TypeId {get;set;} public int? AttachedFileId {get;set;} }
Мне необходимо для каждого родителя получить признак наличия того или иного типа. Наличием считается что отсутствуют item без прикрепленного файла, написал следующий запрос:
var items = _context.Set() .GroupBy(x=>x.ParentId) .Select(x=>new { ParentId = x.Key, Type1 = x.Where(x=>x.TypeId==1).Any() && x.Where(x=>x.TypeId==1).All(x=>x.AttachedFileId!=null) //И так для каждого типа })
Запрос возвращает данные так как мне необходимо, но мне кажется что условие x.Where(x=>x.TypeId==1).Any() && x.Where(x=>x.TypeId==1).All(x=>x.AttachedFileId!=null) можно переписать
Также меня смущает, что метод All для пустой коллекции возвращает true
Пример на fiddle


Ответ

С точки зрения математики всё верно: метод All — это аналог квантора всеобщности, а для пустых множеств он всегда верен, независимо от условия.
Этот метод реализован так (за вычетом проверок):
public static bool All(this IEnumerable source, Func predicate) { foreach (TSource element in source) if (!predicate(element)) return false; return true; }
Упростить ваше выражение что-то не очень получается. Разве что нагромоздить переменные для одного прохода, но с грубым нарушением идеи функциональщины:
bool any = false; bool result = x.Where(x => any = x.TypeId == 1).All(x => x.AttachedFileId != null) && any;

Комментариев нет:

Отправить комментарий