Що є протилежним методом Any <T>


80

Як я можу перевірити у Linq, якщо колекція не містить об’єкта. Тобто протилежність Any<T>.

Я міг інвертувати результат за допомогою, !але для читабельності я задався питанням, чи є кращий спосіб зробити це? Чи слід додавати розширення самостійно?


Тоді читабельніше !? Contains, Exists?
Тігран

3
Так, немає None<T>. Я часто використовую такі спеціальні розширення для читабельності (наприклад, мені не подобається !dictionary.ContainsKey(key)синтаксис, тому я застосував dictionary.NoKey(key)натомість.
Konrad Morawski,

2
@Morawski: Я почав використовувати ConcurrentDictionary, тому що це дуже зручний GetOrAddметод, навіть коли мені не потрібна паралельність.
Роджер Ліпскомб

Відповіді:


87

Ви можете легко створити Noneметод розширення:

public static bool None<TSource>(this IEnumerable<TSource> source)
{
    return !source.Any();
}

public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    return !source.Any(predicate);
}

1
Я вважаю, що це було б гарним доповненням до стандартного Linq.
Іван

3
@Ivan, справа не в самому Linq, але це частина моєї бібліотеки Linq.Extras
Thomas Levesque

60

Навпаки перевірці того, що будь-який (принаймні один) запис відповідає певним критеріям, було б підтвердження того, що всі записи не відповідають критеріям.

Ви не опублікували повний приклад, але якщо хотіли протилежне чомусь:

var isJohnFound = MyRecords.Any(x => x.FirstName == "John");

Ви можете використовувати:

var isJohnNotFound = MyRecords.All(x => x.FirstName != "John");

Щойно натрапив на це сьогодні в Google, і хоча я погоджуюся з вашим підходом, я зазвичай використовуюvar isJohnNotFound = !MyRecords.All(x => x.FirstName == "John");
Кріс

Звичайно, я по-дурному. Коли я це роблю, не перевіряється жодне поле. Зазвичай це більше схоже на !MyRecords.All(x => InvalidNames.Any(n => n == x.Name));Так перевіряйте кожен запис у списку недійсних імен, лише якщо жоден збіг не буде результатом істинним.
Кріс

2

На додаток до доданих відповідей, якщо ви не хочете обертати Any()метод, ви можете реалізувати None()наступне:

public static bool None<TSource>(this IEnumerable<TSource> source) 
{
    if (source == null) { throw new ArgumentNullException(nameof(source)); }

    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        return !enumerator.MoveNext();
    }
}

public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null) { throw new ArgumentNullException(nameof(source)); }
    if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); }

    foreach (TSource item in source)
    {
        if (predicate(item))
        {
            return false;
        }
    }

    return true;
}

На додаток до цього для безпараметричного перевантаження ви можете застосувати ICollection<T>оптимізацію, яка насправді не існує в реалізації LINQ.

ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null) { return collection.Count == 0; }

2

Знайшов цю тему, коли я хотів з'ясувати, чи не містить колекція одного об'єкта, але я не хочу перевіряти, чи всі об'єкти в колекції відповідають заданим критеріям. У підсумку я зробив таку перевірку:

var exists = modifiedCustomers.Any(x => x.Key == item.Key);

if (!exists)
{
    continue;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.