簡體   English   中英

C# 是否有用於 List/IEnumerable 的 IsNullOrEmpty?

[英]Does C# have IsNullOrEmpty for List/IEnumerable?

我知道通常空列表比 NULL 更可取。 但我要返回 NULL,主要有兩個原因

  1. 我必須明確地檢查和處理空值,避免錯誤和攻擊。
  2. 執行起來容易?? 之后進行操作以獲得返回值。

對於字符串,我們有 IsNullOrEmpty。 C# 本身是否有任何東西對 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 采取了額外的步驟,即強制轉換為 ICollection(在可能的情況下)。 我不會想到要做的事情。

后期更新:從 C# 6.0 開始,可以使用空傳播運算符來表達簡潔,如下所示:

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

或者,作為IEnumerable<T>的更清潔和更通用的替代方案:

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

注意 1:與 OP 問題(引用)相反,所有上層變體實際上都反映IsNotNullOrEmpty

由於運算符優先級, IsNullOrEmpty等效項看起來不那么吸引人:
if (!(list?.Count > 0))

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

?. 如果子成員為null null 但是 [...] 如果我們嘗試獲取一個非Nullable成員,例如Any()方法,它返回bool [...] 編譯器將在Nullable<>中“包裝”一個返回值。 例如, Object?.Any()會給我們bool? (這是Nullable<bool> ),而不是bool [...] 因為它不能被隱式轉換為bool ,所以這個表達式不能在if中使用

注 3:作為獎勵,該語句也是“線程安全的”(引自 answer of this question ):

在多線程上下文中,如果 [ enumerable ] 可以從另一個線程訪問(因為它是一個可訪問的字段,或者因為它在暴露給另一個線程的 lambda 中被關閉),那么每次計算時值可能不同 [ ieprior null -檢查]

沒有內置任何東西。

這是一個簡單的擴展方法:

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

如果您需要能夠在它不為空的情況下檢索所有元素,那么這里的一些答案將不起作用,因為對不可回退的枚舉的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;
     }
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM