web-dev-qa-db-ja.com

IEnumerableがnullまたは空かどうかを確認する方法は?

string.IsNullOrEmptyメソッドが大好きです。 IEnumerableに同じ機能を許可するものが欲しいです。そのようなものはありますか?たぶんいくつかのコレクションヘルパークラス?私が尋ねている理由は、パターンが(mylist != null && mylist.Any())の場合、ifステートメントでコードが乱雑に見えるためです。 Foo.IsAny(myList)を使用する方がずっときれいです。

この投稿はその答えを与えません: IEnumerable is empty?

135
Schultz9999

確かにcouldと書いてください:

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}

ただし、すべてのシーケンスが繰り返し可能ではないことに注意してください。 一般的に念のため、一度だけ歩くことを好みます。

168
Marc Gravell
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}
114
Matt Greer

静的ラッパークラスを含む@Matt Greerの便利な回答の修正版を次に示します。これにより、これを新しいソースファイルにコピーして貼り付けることができ、Linqに依存せず、値のボクシングを避けるために汎用のIEnumerable<T>オーバーロードを追加します非ジェネリックバージョンで発生するタイプ。 [編集:IEnumerable<T>を使用しても列挙子のボックス化は防止されないことに注意してください。 duck-typing はそれを防止できませんが、少なくとも値型コレクションの要素はそれぞれボックス化されません。

using System.Collections;
using System.Collections.Generic;

public static class IsNullOrEmptyExtension
{
    public static bool IsNullOrEmpty(this IEnumerable source)
    {
        if (source != null)
        {
            foreach (object obj in source)
            {
                return false;
            }
        }
        return true;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source != null)
        {
            foreach (T obj in source)
            {
                return false;
            }
        }
        return true;
    }
}
20
yoyo

別の方法は、列挙子を取得し、MoveNext()メソッドを呼び出して、アイテムがあるかどうかを確認することです。

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

これは、IEnumerable <T>と同様にIEnumerableでも機能します。

13
Darren

いくつかの最新のC#機能を利用した、私が行う方法:

オプション1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

オプション2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

ところで、コレクションが空かどうかを確認するためだけにCount == 0Count() == 0を使用しないでください。常にLinqの.Any()を使用します

6
Ronald Rey

これは役立つかもしれません

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

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

C#6以降では、 null伝搬myList?.Any() == trueを使用できます

まだこれがあまりにも詰まっていると思うか、良いol '拡張方法を好むなら、Matt GreerとMarc Gravellの答えをお勧めしますが、完全性のために少し拡張された機能を備えています。

それらの回答は同じ基本機能を提供しますが、それぞれが別の観点からのものです。 Mattの答えは string.IsNullOrEmpty -mentalityを使用しますが、Marcの答えはLinqの.Any()ロードを使用して作業を完了します。

私は個人的に .Any() roadを使用しますが、メソッドの other overload から条件チェック機能を追加したいと思います。

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
    {
        if (source == null) return false;
        return predicate == null
            ? source.Any()
            : source.Any(predicate);
    }

したがって、通常のmyList.AnyNotNull(item=>item.AnswerToLife == 42);でできるように.Any()を実行できますが、nullチェックを追加します

C#6の方法では、myList?.Any()が `boolではなくbool?を返すことに注意してください。これはpropagatingnullの実際の効果です

3
Thomas Mulder

Marc Gravell's answer のコードと、使用例があります。

using System;
using System.Collections.Generic;
using System.Linq;

public static class Utils
{
    public static bool IsAny<T>(this IEnumerable<T> data)
    {
        return data != null && data.Any();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        if (items.IsAny())
        {
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }
        else
        {
            Console.WriteLine("No items.");
        }
    }
}

彼が言うように、すべてのシーケンスが反復可能であるとは限らないため、IsAny()がシーケンスのステップ実行を開始するため、コードが問題を引き起こすことがあります。 Robert Harveyの答え の意味は、nulland空を確認する必要がないことが多いということだと思います。多くの場合、nullをチェックしてからforeachを使用できます。

シーケンスを2回開始することを避け、foreachを利用するために、次のようなコードを作成しました。

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        bool isEmpty = true;
        if (items != null)
        {
            foreach (var item in items)
            {
                isEmpty = false;
                Console.WriteLine(item);
            }
        }
        if (isEmpty)
        {
            Console.WriteLine("No items.");
        }
    }
}

拡張メソッドを使用すると、数行の入力が節約されると思いますが、このコードは私にとってより明確に見えます。 IsAny(items)が実際にシーケンスのステップ実行を開始することにすぐに気付かない開発者もいると思います。 (もちろん、多くのシーケンスを使用している場合、それらをどのステップで実行するかをすぐに考えることができます。)

2
Don Kirkby

Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);を使用します。お役に立てれば。

壊す:

Collection?.Any()は、Collectionがnullの場合はnullを返し、Collectionが空の場合はfalseを返します。

Collection?.Any()??falseは、Collectionが空の場合はfalseを、Collectionがfalseの場合はnullを返します。

これを補完すると、IsEmptyOrNullが得られます。

これは @ Matt Greerによる回答

彼はOPの質問に完璧に答えました。

Anyの元の機能を維持しながら、nullもチェックしながら、このようなものが必要でした。他の誰かが同様のものを必要とする場合に備えて、私はこれを投稿しています。

特に、述語を渡すことができるようにしたかったのです。

public static class Utilities
{
    // Will return true if it is not null and contains elements.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable)
    {
        return enumerable != null && enumerable.Any();
    }

    // Will return true if it is not null and contains elements that satisfy the condition.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
    {
        return enumerable != null && enumerable.Any(predicate);
    }
}

拡張メソッドの命名の方がおそらく良いでしょう。

1
kb4000
if (collection?.Any() == true){
    // if collection contains more than one item
}
if (collection?.Any() != true){
    // if collection is null
    // if collection does not contain any item
}
1
Scholtz

私は同じ問題を抱えていて、次のように解決します:

    public bool HasMember(IEnumerable<TEntity> Dataset)
    {
        return Dataset != null && Dataset.Any(c=>c!=null);
    }

「c => c!= null」は、すべてのヌルエンティティを無視します。

1
Hosein Djadidi

1回の読み取りで一部のリソースが使い果たされるため、従来の個別のチェックではなく、チェックと読み取りを組み合わせてから読み取りを行うのはなぜかと考えました。

最初に、より単純なnullのインライン拡張のチェック用のものがあります。

public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));

var first = source.ThrowOnNull().First();

それから、もう少し関与します(少なくとも、私が書いた方法では)、null-and-emptyのインライン拡張をチェックします。

public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
  using (var e = source.ThrowOnNull(paramName).GetEnumerator())
  {
    if (!e.MoveNext())
    {
      throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
    }

    do
    {
      yield return e.Current;
    }
    while (e.MoveNext());
  }
}

var first = source.ThrowOnNullOrEmpty().First();

もちろん、コールチェーンを継続せずに両方を呼び出すことができます。また、paramNameを含めました。これにより、呼び出し元がチェックされている「ソース」ではない場合、エラーの代替名を含めることができます。 「nameof(ターゲット)」。

0
Rob

私はそれを確認するために簡単な場合を使用しました

私の解決策をチェックしてください

foreach (Pet pet in v.Pets)
{
    if (pet == null)
    {
        Console.WriteLine(" No pet");// enumerator is empty
        break;
    }
    Console.WriteLine("  {0}", pet.Name);
}
0

using System.Linqを追加するだけで、IEnumerableで使用可能なメソッドにアクセスしようとしたときに発生する魔法を確認できます。これを追加すると、Count()という名前のメソッドに簡単にアクセスできます。 count()を呼び出す前にnull valueを確認することを忘れないでください:)

0
Mohit

空かどうかをチェックするための以下のような他の最良の解決策は?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}
0
Shakeer Hussain

私はこれを使用します:

    public static bool IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

エジェム:

List<string> Things = null;
if (Things.IsNotEmpty())
{
    //replaces ->  if (Things != null && Things.Count > 0) 
}
0
Jhollman