C# 有 List/IEnumerable IsNullOrEmpty 吗?

发布于 2024-12-22 08:27:21 字数 208 浏览 1 评论 0原文

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

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

对于字符串,我们有 IsNullOrEmpty。 C# 本身是否有任何东西可以为 List 或 IEnumerable 做同样的事情?

I know generally empty List is more prefer than NULL. But I am going to return NULL, for mainly two reasons

  1. I have to check and handle null values explicitly, avoiding bugs and attacks.
  2. It is easy to perform ?? operation afterwards to get a return value.

For strings, we have IsNullOrEmpty. Is there anything from C# itself doing the same thing for List or IEnumerable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

瘫痪情歌 2024-12-29 08:27:21

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

参见此处

/// <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(如果可能)。有些事是我没想过要做的。

nothing baked into the framework, but it's a pretty straight forward extension method.

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 takes the extra step of casting to ICollection (where possible) for performance reasons. Something I would not have thought to do.

金兰素衣 2024-12-29 08:27:21

最新更新:从 C# 6.0 开始,空传播运算符可用于表达简洁,如下所示:

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

或者,作为 IEnumerableIEnumerable的更清晰、更通用的替代方案。 T>

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

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

由于运算符优先级 IsNullOrEmpty 等价物看起来不太吸引人:
if (!(列表?.Count > 0))

注释 2: ?? false 是必要的,因为以下原因(来自 这篇文章):

如果子成员为 null

?. 运算符将返回 null
但是 [...] 如果我们尝试获取一个非 Nullable 成员,例如
Any() 方法,返回 bool [...] 编译器将
将返回值“包装”在 Nullable 中。例如,Object?.Any()
给我们 bool? (即 Nullable),而不是 bool
[...] 由于它不能隐式转换为 bool,因此该表达式不能在 if

中使用

注释 3: 作为奖励,该语句也是“线程安全的”(引用 这个问题):

在多线程上下文中,如果[可枚举]可以从另一个线程访问
线程(要么因为它是一个可访问的字段,要么因为它是
封闭在暴露给另一个线程的 lambda 中)然后
每次计算时的值可能不同[即之前的空检查]

Late update: since C# 6.0, the null-propagation operator may be used to express concise like this:

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

or, as a cleaner and more generic alternative for IEnumerable<T>:

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

Note 1: all upper variants reflect actually IsNotNullOrEmpty, in contrast to OP question (quote):

Because of operator precedence IsNullOrEmpty equivalents look less appealing:
if (!(list?.Count > 0))

Note 2: ?? false is necessary, because of the following reason (summary/quote from this post):

?. operator will return null if a child member is null.
But [...] if we try to get a non-Nullable member, like the
Any() method, that returns bool [...] the compiler will
"wrap" a return value in Nullable<>. For example, Object?.Any() will
give us bool? (which is Nullable<bool>), not bool.
[...] Since it can't be implicitly casted to bool this expression cannot be used in the if

Note 3: as a bonus, the statement is also "thread-safe" (quote from answer of this question):

In a multithreaded context, if [enumerable] is accessible from another
thread (either because it's a field that's accessible or because it's
closed over in a lambda that is exposed to another thread) then the
value could be different each time it's computed [i.e.prior null-check]

梦断已成空 2024-12-29 08:27:21

没有内置任何内容。

不过它是一个简单的扩展方法:

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

  return !enumerable.Any();
}

There is nothing built in.

It is a simple extension method though:

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

  return !enumerable.Any();
}
|煩躁 2024-12-29 08:27:21
var nullOrEmpty = list == null || !list.Any();
var nullOrEmpty = list == null || !list.Any();
老旧海报 2024-12-29 08:27:21

将前面的答案汇总到 C# 6.0+ 的简单扩展方法中:

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

Putting together the previous answers into a simple extension method for C# 6.0+:

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;
转角预定愛 2024-12-29 08:27:21

如果您需要能够在不为空的情况下检索所有元素,那么此处的某些答案将不起作用,因为在非对象上调用 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()).ToList() 等。

If you need to be able to retrieve all of the elements in the case of it not being empty, then some of the answers here won't work, because the call to Any() on a non-rewindable enumerable will "forget" an element.

You could take a different approach and turn nulls into empties:

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).
}

Likewise (someEnumeration ?? Enumerable.Empty<MyType>()).ToList() etc. can be used.

看春风乍起 2024-12-29 08:27:21

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

As everyone else has said, nothing is built into the framework, but if you are using Castle then Castle.Core.Internal has it.

using Castle.Core.Internal;

namespace PhoneNumbers
{
    public class PhoneNumberService : IPhoneNumberService
    {
        public void ConsolidateNumbers(Account accountRequest)
        {
            if (accountRequest.Addresses.IsNullOrEmpty()) // Addresses is List<T>
            {
                return;
            }
            ...
南…巷孤猫 2024-12-29 08:27:21

我今天注意到 .Net Core 7.6.2 在 Microsoft.Identitymodel.Tokens.CollectionUtilities

恕我直言,这似乎是一个非常奇怪的地方,但是如果您正在使用该软件包,那么它就可用......

I noticed today that .Net Core 7.6.2 has the extension CollectionUtilities.IsNullOrEmpty<T>(IEnumerable<T>) Method in Microsoft.Identitymodel.Tokens.CollectionUtilities.

This seems a very odd place to keep it IMHO, but if you're using that package then it is available...

墟烟 2024-12-29 08:27:21

我修改了 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());
}

I modified the suggestion from Matthew Vines to avoid the "Possible multiple enumeration of IEnumerable" - problem.
(see also the comment from Jon Hanna)

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

... and the unit test:

[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());
}
别理我 2024-12-29 08:27:21
var nullOrEmpty = !( list?.Count > 0 );
var nullOrEmpty = !( list?.Count > 0 );
洋洋洒洒 2024-12-29 08:27:21

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

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable?.Any() ?? true;
}

for me best isNullOrEmpty method is looked like this

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return !enumerable?.Any() ?? true;
}
剩余の解释 2024-12-29 08:27:21
 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 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;
     }
 }
思慕 2024-12-29 08:27:21

具有可为空支持的一行:

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

One-line with nullable support:

public static bool IsNullOrEmpty<T>(this IEnumerable<T>? enumerable) => 
            enumerable == null || !enumerable.Any();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文