Страницы

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

понедельник, 9 декабря 2019 г.

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

#c_sharp #net #linq #инспекция_кода


У меня есть класс 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
    


Ответы

Ответ 1



С точки зрения математики всё верно: метод 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;

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

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