web-dev-qa-db-ja.com

リスト全体を列挙せずに、IEnumerableに行があるかどうかを確認します

タイプIEnumerableTを返す次のメソッドがあります。 yield returnから遅延読み込みIEnumerableを除いて、メソッドの実装は重要ではありません。結果として何百万ものアイテムが含まれる可能性があるため、これが必要です。

public IEnumerable<T> Parse()
{
    foreach(...)
    {
        yield return parsedObject;
    }
}

問題:

IEnumerableにアイテムがあるかどうかを判断するために使用できる次のプロパティがあります。

public bool HasItems
{
    get
    {
        return Parse().Take(1).SingleOrDefault() != null;
    }
}

これを行うためのより良い方法はおそらくありますか?

14
Dave New

IEnumerable.Any()は、シーケンスに要素がある場合はtrueを返し、シーケンスに要素がない場合はfalseを返します。このメソッドは、最初の要素を通過した場合はtrueを返し、通過しなかった場合はfalseを返すため、シーケンス全体(最大1つの要素のみ)を反復しません。

34
Marcus

ハウツー:反復せずにIEnumerable <T>からアイテムをカウントしますか?Enumerablelazy、先読みの「リスト」、そして量子力学のように、それを調査する行為はその状態を変えます。

確認を参照してください: https://dotnetfiddle.net/GPMVXH

_    var sideeffect = 0;
    var enumerable = Enumerable.Range(1, 10).Select(i => {
        // show how many times it happens
        sideeffect++;
        return i;
    });

    // will 'enumerate' one item!
    if(enumerable.Any()) Console.WriteLine("There are items in the list; sideeffect={0}", sideeffect);
_

enumerable.Any()は、リストに項目があるかどうかを確認する最もクリーンな方法です。 if(null != (list = enumerable as ICollection<T>) && list.Any()) return trueのような怠惰ではないものにキャストしてみることができます。

または、シナリオでEnumeratorを使用し、列挙する前に予備チェックを行うことが許可されている場合があります。

_var e = enumerable.GetEnumerator();
// check first
if(!e.MoveNext()) return;
// do some stuff, then enumerate the list
do {
    actOn(e.Current);  // do stuff with the current item
} while(e.MoveNext()); // stop when we don't have anything else
_
2
drzaus