web-dev-qa-db-ja.com

C#にはList / IEnumerableのIsNullOrEmptyがありますか?

一般に、空のリストの方がNULLよりも望ましいことを知っています。ただし、主に2つの理由から、NULLを返します。

  1. Null値を明示的にチェックおよび処理し、バグや攻撃を回避する必要があります。
  2. 簡単に実行できます??操作後、戻り値を取得します。

文字列の場合、IsNullOrEmptyがあります。 C#自体から ListまたはIEnumerableに対して同じことをしていますか?

64
Eric Yin

フレームワークに焼き付けられたものは何もありませんが、それは非常に単純な拡張メソッドです。

こちらを参照

/// <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(可能な場合)にキャストする追加の手順を実行します。私がやろうとは思わなかったことでしょう。

66
Matthew Vines

後期更新:C#6.0以降、null-propagation operatorを使用してこのように簡潔に表現できます:

_if (enumerable?.Any() ?? false)
_

注1:_?? false_は、次の理由のために必要です( この投稿 )からの要約/引用):

_?._演算子は、子メンバーがnullの場合、nullを返します。 [...] Nullable [...]を返すAny()メソッドのような非boolメンバーを取得しようとすると、コンパイラは " _Nullable<>_で戻り値をラップします。たとえば、Object?.Any()は、boolではなく、_bool?_(_Nullable<bool>_)を返します。 [...]暗黙的にboolにキャストできないため、この式はifで使用できません

注2:ボーナスとして、ステートメントは「スレッドセーフ」です( この質問 の回答からの引用):

マルチスレッドコンテキストで、[enumerable]が別のスレッドからアクセス可能な場合(アクセス可能なフィールドであるか、別のスレッドに公開されているラムダで閉じられているため)値は計算されるたびに異なる可能性があります[ieprior null-check]

38
Teodor Tite

何も組み込まれていません。

ただし、これは単純な拡張メソッドです。

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

  return !enumerable.Any();
}
24
Oded
var nullOrEmpty = list == null || !list.Any();
9
Justin Niessner

上記の回答をC#6.0+の簡単な拡張メソッドにまとめます。

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

他の誰もが言ったように、フレームワークには何も組み込まれていませんが、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
Matt Frear

空でない場合にすべての要素を取得できるようにする必要がある場合、巻き戻し不可能な列挙型のAny()の呼び出しは要素を「忘れる」。

別のアプローチを取り、nullを空に変えることもできます。

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

私にとって最高のisNullOrEmptyメソッドは次のようになります

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

「IEnumerableの可能な複数列挙」問題を回避するために、Matthew Vinesからの提案を修正しました。 (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());
}
0
Georg