Как проверить, является ли IEnumerable нулевым или пустым?



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



этот пост не дает такого ответа:IEnumerable пуст?.

806   14  

14 ответов:

уверен, что вы может пишут, что:

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

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

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}

вот модифицированная версия полезного ответа @Matt Greer, которая включает статический класс-оболочку, поэтому вы можете просто скопировать-вставить это в новый исходный файл, не зависит от Linq и добавляет общий IEnumerable<T> перегрузка, чтобы избежать бокса типов значений, которые будут происходить с неродовой версией. [EDIT: обратите внимание, что использование IEnumerable<T> не предотвращает бокс перечислителя,утка-типирование не могу этого предотвратить, но, по крайней мере, элементы в коллекции с типом значения не будут каждый упакованный.]

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;
    }
}

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

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

это работает для IEnumerable, а также IEnumerable.

как я это делаю, пользуясь некоторыми современными функциями 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 .Any()

здесь код Марк Gravell-это, а также пример его использования.

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и пустой. Часто, вы можете просто проверить на null, а затем использовать foreach.

To избегайте запуска последовательности дважды и воспользоваться 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) начнет шагать через последовательность. (Конечно, если вы используете много последовательностей, вы быстро научитесь думать о том, какие шаги сквозь них.)

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

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

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

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

    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() возвращает a bool? а не типа bool, которое, по сути распространяющейся null

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

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;
}

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

поломки:

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

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

дополнение, которое даст нам IsEmptyOrNull.

У меня была такая же проблема и я решаю ее так :

    public bool HasMember(IEnumerable<TEntity> Dataset)
    {
        return Dataset != null && Dataset.Any(c=>c!=null);
    }

" c= > c!=null " будет игнорировать все нулевые сущности.

просто добавить using System.Linq и увидеть волшебство происходит, когда вы пытаетесь получить доступ к доступных способов в IEnumerable. Добавление этого даст вам доступ к методу с именем Count() вот так просто. просто не забудьте проверить null value перед вызовом count() :)

я использовал простой, если проверить его

проверить мое решение

foreach (Pet pet in v.Pets)
{
    if (pet == null)
    {
        Console.WriteLine(" No pet");// enumerator is empty
        break;
    }
    Console.WriteLine("  {0}", pet.Name);
}

Я построил это от ответ @Matt Greer

он отлично ответил на вопрос ОП.

Я хотел что-то вроде этого, сохраняя исходные возможности любого, а также проверяя null. Я отправляю это на случай, если кому-то еще нужно что-то подобное.

в частности, я хотел все еще быть в состоянии передать предикат.

public static class Utilities
{
    // Will return true if it is not null and contains elements.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable)
    {
        return enumerable != null && enumerable.Any();
    }

    // Will return true if it is not null and contains elements that satisfy the condition.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
    {
        return enumerable != null && enumerable.Any(predicate);
    }
}

название метода расширения, вероятно, может быть лучше.

другое лучшее решение, как показано ниже, чтобы проверить пустой или нет ?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}

Comments

    Ничего не найдено.