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

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

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

Ответ 1

Уверен, что мог написать:

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

Это работает для IEnumerable, а также IEnumerable <T> .

Ответ 5

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

Вариант 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()

Ответ 6

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

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

Ответ 7

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

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

Их ответы обеспечивают одну и ту же базовую функциональность, но с другой стороны. Мэтт отвечает string.IsNullOrEmpty -mentality, тогда как ответ Marc берет путь Linq .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(), но с добавленной нулевой проверкой

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

Ответ 8

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

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.

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

Ответ 9

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

Структура:

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

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

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

Ответ 10

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
}

Ответ 11

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

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

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

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

public static class Utilities
{
    /// <summary>
    /// Determines whether a sequence has a value and contains any elements.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
    /// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source?.Any() == true;
    }

    /// <summary>
    /// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
    /// <param name="predicate">A function to test each element for a condition.</param>
    /// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        return source?.Any(predicate) == true;
    }
}

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

Ответ 12

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

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

"c = > c!= null" игнорирует все пустые объекты.

Ответ 13

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

Ответ 14

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

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

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

Ответ 15

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

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

Ответ 16

Я использую это:

    public static bool IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

Ejem:

List<string> Things = null;
if (Things.IsNotEmpty())
{
    //replaces ->  if (Things != null && Things.Count > 0) 
}

Ответ 17

Поскольку некоторые ресурсы исчерпываются после одного чтения, я подумал, почему бы не объединить проверки и чтения вместо традиционной отдельной проверки, а затем прочитать.

Сначала у нас есть один для более простого встроенного расширения check-for-null:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));

var first = source.ThrowOnNull().First();

Тогда нам нужно немного больше (ну, по крайней мере, так, как я это написал) встроенное расширение для проверки на пустое и пустое:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
  using (var e = source.ThrowOnNull(paramName).GetEnumerator())
  {
    if (!e.MoveNext())
    {
      throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
    }

    do
    {
      yield return e.Current;
    }
    while (e.MoveNext());
  }
}

var first = source.ThrowOnNullOrEmpty().First();

Конечно, вы можете звонить обоим без продолжения цепочки вызовов. Кроме того, я включил paramName, чтобы вызывающая сторона могла включить альтернативное имя для ошибки, если она не проверяется как "источник", например, "Nameof (цель)".

Ответ 18

 public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source != null && source.Any();
    }

мой собственный метод расширения, чтобы проверить Не нуль и Любой