4

次のコードに基づく:

 var grouped = filters.GroupBy(p => p.PropertyName);
                 int numOfRowElements = grouped.Count();
     foreach (IGrouping<string, PropertyFilter> filter in grouped)
                {


                    foreach (var propertyFilter in filter)
                    {
                        // do something
                    }

                }

リストをフィルタリングする場合、私の理解では、IEnumerable.Count()を呼び出すと、クエリが強制的に実行されます。この実行の結果はグループ化された変数に格納され、foreachループで使用されますか、それともforeachループはクエリを強制的に再実行しますか?代わりにこれを行う方が良いでしょうか?

 var grouped = filters.GroupBy(p => p.PropertyName).ToList();
  int numOfRowElements = grouped.Count;
     foreach (IGrouping<string, PropertyFilter> filter in grouped)
                {


                    foreach (var propertyFilter in filter)
                    {
                        // do something
                    }

                }

TIA。

4

1 に答える 1

5

IList<T>基になるデータソースが の場合Enumerable.Count()、はプロパティを最適化として呼び出すため、.Countパフォーマンスの低下はありません*。そうでない場合、列挙が強制されます。これを慎重に検討してください。

var someList = new List<int>(); 
var count = someList.Count(); // will use .Count property
var count = someList.OrderBy(x => x).Count(); // will force enumeration 

この例では、2 番目のステートメントでリストの数を取得しているだけです。3 番目では、リストを並べ替えてからカウントを取得しています。リストを並べ替えると、リストではなくシーケンスが返されます。したがって、このCount()メソッドはではなくで動作します。この場合、クエリを列挙して結果を取得する必要があり、それに伴うコスト (この場合は順序付け) が発生します。IList<T>IEnumerable<T>

これに照らして、最初のスニペットでは、クエリを 2 回列挙します。カウントを取得するために 1 回、foreach で 1 回。これにより、データを 2 回グループ化するためのすべてのロジックが実行されます。2 番目の例では、グループ化操作を 1 回だけ実行しますが、結果のリストを foreach で反復処理することは明らかです。これは、グループ化操作を 2 回実行するよりもコストが低くなります。(節約を測定できるかどうかは、元のリストのデータのサイズおよび/またはソースに完全に依存します。疑わしい場合は、プロファイルを作成してください。)


*間接化のレイヤーには測定されたわずかなペナルティが存在する可能性があります。これが真のボトルネックであると思われる場合は、プロファイルを作成する必要があります。しかし、Count()方法を次のように考えてください。

if (sequence is IList<T>) 
{
    return ((IList<T>)sequence).Count
}
else 
{
   /* perform enumeration */;
}
于 2011-10-05T15:51:58.733 に答える