Есть ли в C # IsNullOrEmpty для List / IEnumerable? - PullRequest
64 голосов
/ 21 декабря 2011

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

  1. Я должен явно проверять и обрабатывать нулевые значения, избегая ошибок и атак.
  2. После этого легко выполнить ?? операцию, чтобы получить возвращаемое значение.

Для строк у нас есть IsNullOrEmpty. Что-нибудь из самого C # делает то же самое для List или IEnumerable?

Ответы [ 10 ]

66 голосов
/ 21 декабря 2011

ничего не запечено в фреймворке, но это довольно простой метод расширения.

Смотрите здесь

/// <summary>
    /// Determines whether the collection is null or contains no elements.
    /// </summary>
    /// <typeparam name="T">The IEnumerable type.</typeparam>
    /// <param name="enumerable">The enumerable, which may be null or empty.</param>
    /// <returns>
    ///     <c>true</c> if the IEnumerable is null or empty; otherwise, <c>false</c>.
    /// </returns>
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
    {
        if (enumerable == null)
        {
            return true;
        }
        /* If this is a list, use the Count property for efficiency. 
         * The Count property is O(1) while IEnumerable.Count() is O(N). */
        var collection = enumerable as ICollection<T>;
        if (collection != null)
        {
            return collection.Count < 1;
        }
        return !enumerable.Any(); 
    }

Даниэль Воган делает дополнительный шаг приведения к ICollection (где это возможно) по соображениям производительности. Что-то, чего я бы не подумал сделать.

38 голосов
/ 31 января 2017

Позднее обновление : начиная с C # 6.0 оператор с нулевым распространением может использоваться для краткого выражения, например:

if (enumerable?.Any() ?? false)

Примечание 1: ?? false необходимо по следующей причине (резюме / цитата из этого сообщения ):

?. оператор вернет null, если дочерний элемент равен null. Но [...] если мы попытаемся получить не Nullable члена, как Any() метод, который возвращает bool [...] компилятор «обернуть» возвращаемое значение в Nullable<>. Например, Object?.Any() будет дайте нам bool? (то есть Nullable<bool>), а не bool. [...] Поскольку оно не может быть неявно приведено к bool, это выражение нельзя использовать в if

Примечание 2: в качестве бонуса, заявление также является "поточно-ориентированным" (цитата из ответа на этот вопрос ):

В многопоточном контексте, если [ enumerable ] доступен из другого поток (или потому, что это поле, которое доступно или потому что это закрыт в лямбду, которая подвергается воздействию другого потока), то значение может отличаться при каждом вычислении [ i.e.prior null-check ]

24 голосов
/ 21 декабря 2011

Ничего не встроено.

Это простой метод расширения:

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
  if(enumerable == null)
    return true;

  return !enumerable.Any();
}
9 голосов
/ 21 декабря 2011
var nullOrEmpty = list == null || !list.Any();
1 голос
/ 11 марта 2017

Объединение предыдущих ответов в простой метод расширения для C # 6.0 +:

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;
1 голос
/ 19 марта 2014

Как и все остальные, в фреймворк ничего не встроено, но если вы используете Castle, то у Castle.Core.Internal это есть.

using Castle.Core.Internal;

namespace PhoneNumbers
{
    public class PhoneNumberService : IPhoneNumberService
    {
        public void ConsolidateNumbers(Account accountRequest)
        {
            if (accountRequest.Addresses.IsNullOrEmpty()) // Addresses is List<T>
            {
                return;
            }
            ...
1 голос
/ 21 декабря 2011

Если вам нужно иметь возможность извлечь все элементы в случае, если они не пусты, то некоторые ответы здесь не сработают, потому что вызов Any() для не перематываемого перечислимого будет "забудьте "элемент.

Вы можете использовать другой подход и превратить нули в пустые:

bool didSomething = false;
foreach(var element in someEnumeration ?? Enumerable.Empty<MyType>())
{
  //some sensible thing to do on element...
  didSomething = true;
}
if(!didSomething)
{
  //handle the fact that it was null or empty (without caring which).
}

Аналогично (someEnumeration ?? Enumerable.Empty<MyType>()).ToList() и т. д. можно использовать.

0 голосов
/ 06 февраля 2019

для меня лучший метод isNullOrEmpty выглядит так

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable?.Any() ?? true;
}
0 голосов
/ 27 сентября 2016
var nullOrEmpty = !( list?.Count > 0 );
0 голосов
/ 18 июля 2016

Я изменил предложение Мэтью Вайнса, чтобы избежать проблемы «Возможное множественное перечисление IEnumerable».(см. также комментарий Джона Ханны)

public static bool IsNullOrEmpty(this IEnumerable items)
    => items == null
    || (items as ICollection)?.Count == 0
    || !items.GetEnumerator().MoveNext();

... и модульный тест:

[Test]
public void TestEnumerableEx()
{
    List<int> list = null;
    Assert.IsTrue(list.IsNullOrEmpty());

    list = new List<int>();
    Assert.IsTrue(list.IsNullOrEmpty());

    list.AddRange(new []{1, 2, 3});
    Assert.IsFalse(list.IsNullOrEmpty());

    var enumerator = list.GetEnumerator();
    for(var i = 1; i <= list.Count; i++)
    {
        Assert.IsFalse(list.IsNullOrEmpty());
        Assert.IsTrue(enumerator.MoveNext());
        Assert.AreEqual(i, enumerator.Current);
    }

    Assert.IsFalse(list.IsNullOrEmpty());
    Assert.IsFalse(enumerator.MoveNext());
}
...