C#是否具有IsNullOrEmpty用于列表/ IEnumerable?

问题描述 投票:64回答:10

我通常知道空列表比NULL更可取。但是我将返回NULL,主要有两个原因

  1. 我必须显式检查并处理空值,以避免错误和攻击。
  2. 随后很容易执行??操作以获得返回值。

对于字符串,我们有IsNullOrEmpty。 来自C#本身是否对List或IEnumerable做相同的事情?

c# ienumerable isnullorempty
10个回答
67
投票

框架中没有任何内容,但这是一个非常简单的扩展方法。

See here

/// <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(); 
    }

出于性能原因,Daniel Vaughan采取了额外的步骤将其强制转换为ICollection。我本来不想做的事情。


-1
投票
var nullOrEmpty = !( list?.Count > 0 );

40
投票

最新更新:自C#6.0起,null-propagation运算符可用于表达简洁性,如下所示:

if (  list?.Count  > 0 ) // For List<T>
if ( array?.Length > 0 ) // For Array<T>

或者,作为IEnumerable<T>的更简洁,更通用的替代方法:

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

注1:与OP问题(IsNotNullOrEmpty)相比,所有较高的变体实际上都反映了quote

由于运算符优先级IsNullOrEmpty等效项看起来不那么吸引人:if (!(list?.Count > 0))

注2: ?? false是必要的,因为以下原因(this post的摘要/引号):

?.运算符将在子成员为null时返回null。但是[...]如果我们尝试获得非Nullable成员,例如Any()方法,返回bool [...]编译器将“包装” Nullable<>中的返回值。例如,Object?.Any()将给我们bool?(即Nullable<bool>),而不是bool。[...]由于无法将其隐式转换为bool,因此无法在if

中使用此表达式

注3:作为奖励,该语句也是“线程安全的”(引自this question的答案):

在多线程上下文中,如果[enumerable]可从另一个访问线程(要么是因为它是可访问的字段,要么是因为在暴露给另一个线程的lambda中关闭),然后每次计算的值可能会有所不同[i.e.prior null-check]


24
投票

没有内置内容。

尽管这是一个简单的扩展方法:

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

  return !enumerable.Any();
}

9
投票
var nullOrEmpty = list == null || !list.Any();

2
投票

将先前的答案汇总为C#6.0+的简单扩展方法:

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;

1
投票

如果在不为空的情况下需要能够检索所有元素,则此处的某些答案将不起作用,因为在不可重绕的枚举上对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()等。


1
投票

正如其他人所说的,框架中没有任何内容,但是如果您使用的是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;
            }
            ...

0
投票

我修改了Matthew Vines的建议,以避免出现“可能的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());
}

0
投票

对我来说,最好的isNullOrEmpty方法看起来像这样

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable?.Any() ?? true;
}
© www.soinside.com 2019 - 2024. All rights reserved.