1

Count()LINQによって提供されるメソッドには、ソースシーケンスが実装されているかどうかをチェックし、実装されている場合はコレクション全体を反復処理するのではなく、プロパティICollection<T>を呼び出すという最適化があることを認識していました。Countこの最適化を使用すると、基礎となるIEnumerable<T>ものは消費されないため、後続の他の呼び出しによって消費される可能性がありますCount()

特に、述語を受け入れるCountのオーバーロードは、各要素の値を検査する必要があるため、そのような最適化を実行しません。

次に、次の完全なプログラムについて考えてみます。

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

namespace count_where_issue
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable<int> items = new List<int> {1, 2, 3, 4, 5, 6};
            IEnumerable<int> evens = items.Where(y => y % 2 == 0);
            int count = evens.Count();
            int first = evens.First();
            Console.WriteLine("count = {0}", count);
            Console.WriteLine("first = {0}", first);
        }
    }
}

印刷する、

count = 3
first = 2

私の予想では、カウントはevensによって返されたシーケンス全体を消費する必要があり、シーケンスには要素が含まれていないためWhere()、後続の呼び出しevens.First()は失敗します。InvalidOperationException

このプログラムがそのように機能するのはなぜですか?IEnumerable<T>私は通常、次の `Count()の呼び出しを使用しようとはしません。この振る舞いに頼るのは賢明ではないでしょうか?

4

3 に答える 3

2

これがあなたの言っていることかどうかはわかりませんがevens.Count()evens.First()両方ともを列挙していitems.Where(...)ます。

これは、次の出力で確認できます。

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<int> items = new List<int> { 1, 2, 3, 4, 5, 6 };
        IEnumerable<int> evens = items.Where(y => isEven(y));

        int count = evens.Count();
        Console.WriteLine("count = {0}", count);

        int first = evens.First();
        Console.WriteLine("first = {0}", first);

    }

    private static bool isEven(int y)
    {
        Console.Write(y + ": ");

        bool result = y % 2 == 0;

        Console.WriteLine(result);    
        return result;
    }
}

これは:

1: False
2: True
3: False
4: True
5: False
6: True
count = 3
1: False
2: True
first = 2
于 2012-06-30T18:02:25.000 に答える
1

Count()が元のIEnumerableに何らかの影響を与えるという印象を与えたものは何ですか?

ドキュメントには、そのようなものについては何も言及されていません...

http://msdn.microsoft.com/en-us/library/bb338038.aspx

于 2012-06-30T18:00:24.907 に答える
1

IEnumerator<T>使えないのはあなたです。ただし、CountとFirstは、それぞれ個別の列挙子を作成します(の呼び出しを介しGetEnumeratorIEnumerable<T>)。

于 2012-06-30T18:02:00.267 に答える