Does C# have IsNullOrEmpty for List/IEnumerable?

本文关键字:IEnumerable List for have IsNullOrEmpty Does | 更新日期: 2023-09-27 18:18:21

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

  1. 我必须明确地检查和处理空值,避免错误和攻击。
  2. 便于后续??操作获取返回值。
对于字符串,我们有IsNullOrEmpty。c#本身的是否有任何对List或IEnumerable做同样的事情?

Does C# have IsNullOrEmpty for List/IEnumerable?

没有嵌入到框架中,但是它是一个非常直接的扩展方法。

看到

/// <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出于性能原因采取了额外的步骤,将类型转换为iccollection(如果可能)。这是我从未想过要做的事。

最新更新:从c# 6.0开始,空值传播运算符可以用来表示如下简洁的表达式:

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

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

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

注1:所有上面的变量实际上反映了IsNotNullOrEmpty,与OP问题(引用)相反:

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

注2: ?? false是必要的,因为以下原因(摘要/引用自本帖子):

如果子成员为null,则

?.操作符返回null。但[…如果我们试图获得非Nullable成员,如Any()方法,返回bool[…]编译器会在Nullable<>中"wrap"返回值。例如,Object?.Any()将给我们bool?(也就是Nullable<bool>),而不是bool。[…因为它不能隐式转换为bool,这个表达式不能在if

中使用。

注释3:作为奖励,该语句也是"线程安全的"(引用自该问题的答案):

在多线程环境中,if [enumerable]可以从另一个线程访问线程(要么因为它是一个可访问的字段,要么因为它是)在暴露给另一个线程的lambda中关闭),然后值每次计算时都可能不同[,即之前null-check

)

没有什么内置的

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

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

将前面的答案组合成c# 6.0+的简单扩展方法:

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

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

如果您需要能够在非空的情况下检索所有元素,那么这里的一些答案将不起作用,因为在不可rewindable enumerable上调用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()

我修改了Matthew Vines的建议,以避免" IEnumerable可能存在的多个枚举" -问题。(参见Jon Hanna的评论)

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());
}
var nullOrEmpty = !( list?.Count > 0 );

对我来说最好的isNullOrEmpty方法是这样的

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable?.Any() ?? true;
}
 public static class IEnumerableExtention
 {
     public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
     {
         if (enumerable == null)
         {
             return true;
         }
 
         using var enumerator = enumerable.GetEnumerator();
 
         var isEmpty = !enumerator.MoveNext();
 
         return isEmpty;
     }
 }

支持可空的一行:

public static bool IsNullOrEmpty<T>(this IEnumerable<T>? enumerable) => 
            enumerable == null || !enumerable.Any();
相关文章: