Каков метод, противоположный Any <T>


80

Как я могу проверить с Linq, если коллекция не содержит объекта. IE Противоположность Any<T>.

Я мог бы инвертировать результат с помощью, !но для удобства чтения я задавался вопросом, есть ли более лучший способ сделать это? Стоит ли самому добавлять расширение?


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

3
Да нет None<T>. Я часто использую такие специальные расширения для удобства чтения (например, мне не нравится !dictionary.ContainsKey(key)синтаксис, поэтому я реализовал его dictionary.NoKey(key)вместо него.
Конрад Моравски,

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
Томас Левеск

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.