Как проверить, является ли IEnumerable нулевым или пустым? - PullRequest
137 голосов
/ 19 февраля 2011

Я люблю string.IsNullOrEmpty метод. Я хотел бы иметь что-то, что позволило бы такую ​​же функциональность для IEnumerable. Есть ли такие? Может быть, какой-нибудь вспомогательный класс коллекции? Причина, по которой я спрашиваю, состоит в том, что в операторах if код выглядит загроможденным, если шаблон (mylist != null && mylist.Any()). Было бы намного чище иметь Foo.IsAny(myList).

Это сообщение не дает ответа: IEnumerable пуст? .

Ответы [ 16 ]

169 голосов
/ 19 февраля 2011

Конечно, вы могли бы написать, что:

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}

однако, будьте осторожны, чтобы не все последовательности были повторяемыми; обычно Я предпочитаю ходить их один раз, на всякий случай.

114 голосов
/ 19 февраля 2011
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}
21 голосов
/ 12 июля 2014

Вот модифицированная версия полезного ответа @Matt Greer, которая включает статический класс-обертку, так что вы можете просто скопировать и вставить это в новый исходный файл, не зависит от Linq и добавляет общую перегрузку IEnumerable<T> для Избегайте упаковки типов значений, которые могут возникнуть с неуниверсальной версией. [РЕДАКТИРОВАТЬ: обратите внимание, что использование IEnumerable<T> не предотвращает упаковку перечислителя, duck-typing не может предотвратить это, но, по крайней мере, элементы в коллекции с типизированным значением не будут помещены в упаковку. ]

using System.Collections;
using System.Collections.Generic;

public static class IsNullOrEmptyExtension
{
    public static bool IsNullOrEmpty(this IEnumerable source)
    {
        if (source != null)
        {
            foreach (object obj in source)
            {
                return false;
            }
        }
        return true;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source != null)
        {
            foreach (T obj in source)
            {
                return false;
            }
        }
        return true;
    }
}
13 голосов
/ 28 ноября 2014

Другим способом было бы получить Enumerator и вызвать метод MoveNext (), чтобы увидеть, есть ли какие-либо элементы:

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

Это работает как для IEnumerable, так и для IEnumerable .

6 голосов
/ 16 сентября 2016

Как я это делаю, используя некоторые современные возможности C #:

Вариант 1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

Вариант 2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

И, кстати, никогда не используйте Count == 0 или Count() == 0 просто чтобы проверить, пуста ли коллекция. Всегда используйте Linq's .Any()

5 голосов
/ 23 мая 2017

Это может помочь

public static bool IsAny<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() == true;
}

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() != true;
}
3 голосов
/ 10 февраля 2017

Начиная с C # 6, вы можете использовать нулевое распространение : myList?.Any() == true

Если вы все еще считаете это слишком засоренным или предпочитаете хороший старый метод расширения, я бы порекомендовал Мэтта Грираи ответы Марка Гравелла, но с расширенной функциональностью для полноты.

Их ответы обеспечивают те же основные функции, но каждый с другой точки зрения.Ответ Мэтта использует string.IsNullOrEmpty -ментальность, тогда как ответ Марка идет по пути .Any() Линка, чтобы выполнить работу.

Я лично склонен использовать .Any() road, но хотел бы добавить функциональность проверки условий из другой перегрузки метода :

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
    {
        if (source == null) return false;
        return predicate == null
            ? source.Any()
            : source.Any(predicate);
    }

Так что вы все еще можете делать такие вещи, как: myList.AnyNotNull(item=>item.AnswerToLife == 42);, как вы могли бы собычный .Any(), но с добавленной пустой проверкой

Обратите внимание, что при использовании C # 6: myList?.Any() возвращает bool? вместо `bool, что является фактическим эффектом распространения ноль

2 голосов
/ 17 мая 2019
if (collection?.Any() == true){
    // if collection contains more than one item
}
if (collection?.Any() != true){
    // if collection is null
    // if collection does not contain any item
}
2 голосов
/ 25 июня 2017

Я использую Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);. Надеюсь, это поможет.

Разбивка:

Collection?.Any() вернет null, если Коллекция пуста, и false, если Коллекция пуста.

Collection?.Any()??false даст нам false, если Коллекция пуста, и false, если Коллекция: null.

Дополнение к этому даст нам IsEmptyOrNull.

2 голосов
/ 08 марта 2013

Вот код из Ответ Марка Гравелла вместе с примером его использования.

using System;
using System.Collections.Generic;
using System.Linq;

public static class Utils
{
    public static bool IsAny<T>(this IEnumerable<T> data)
    {
        return data != null && data.Any();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        if (items.IsAny())
        {
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }
        else
        {
            Console.WriteLine("No items.");
        }
    }
}

Как он говорит, не все последовательности повторяемы, так что код может иногда вызывать проблемы, потому что IsAny() начинает проходить через последовательность. Я подозреваю, что ответ Роберта Харви означал, что вам часто не нужно проверять наличие пустых значений null и . Часто вы можете просто проверить на ноль и затем использовать foreach.

Чтобы не запускать последовательность дважды и воспользоваться foreach, я просто написал такой код:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        bool isEmpty = true;
        if (items != null)
        {
            foreach (var item in items)
            {
                isEmpty = false;
                Console.WriteLine(item);
            }
        }
        if (isEmpty)
        {
            Console.WriteLine("No items.");
        }
    }
}

Полагаю, метод расширения экономит вам пару строк при наборе текста, но этот код кажется мне более понятным. Я подозреваю, что некоторые разработчики не сразу поймут, что IsAny(items) действительно начнет шагать по последовательности. (Конечно, если вы используете много последовательностей, вы быстро научитесь думать, какие шаги через них.)

...