omer schleifer の回答により、ケースをベンチマークし、最終的に作成された IL をチェックして、チェーン句でパフォーマンスが低下しているかどうかを確認することができました..
次の例を見てみましょう。
var numbers = new List<int>() { 1, 2 ,3,4,5,6,7,8,9,10};
IEnumerable<int> query = numbers.Where(x=> x>2 && x<5);
次の IL になります。
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.2 // <>g__initLocal0
IL_0007: ldloc.2 // <>g__initLocal0
...
...
...
IL_0059: ldloc.2 // <>g__initLocal0
IL_005A: stloc.0 // numbers
IL_005B: ldloc.0 // numbers
IL_005C: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_0061: brtrue.s IL_0076
IL_0063: ldnull
IL_0064: ldftn b__1
IL_006A: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_006F: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_0074: br.s IL_0076
IL_0076: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_007B: call System.Linq.Enumerable.Where
IL_0080: stloc.1 // query
IL_0081: ldloc.1 // query
b__1:
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: ble.s IL_000A
IL_0004: ldarg.0
IL_0005: ldc.i4.5
IL_0006: clt
IL_0008: br.s IL_000B
IL_000A: ldc.i4.0
IL_000B: stloc.0 // CS$1$0000
IL_000C: br.s IL_000E
IL_000E: ldloc.0 // CS$1$0000
IL_000F: ret
//チェーンの例:
var numbers = new List<int>() { 1, 2 ,3,4,5,6,7,8,9,10};
IEnumerable<int> query = numbers.Where(x=> x>2).Where(x => x<5);
// 次の IL になります。
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.2 // <>g__initLocal0
IL_0007: ldloc.2 // <>g__initLocal0
IL_0008: ldc.i4.1
...
...
...
IL_0058: nop
IL_0059: ldloc.2 // <>g__initLocal0
IL_005A: stloc.0 // numbers
IL_005B: ldloc.0 // numbers
IL_005C: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_0061: brtrue.s IL_0076
IL_0063: ldnull
IL_0064: ldftn b__1
IL_006A: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_006F: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_0074: br.s IL_0076
IL_0076: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_007B: call System.Linq.Enumerable.Where <--------first where call
IL_0080: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_0085: brtrue.s IL_009A
IL_0087: ldnull
IL_0088: ldftn b__2
IL_008E: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_0093: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_0098: br.s IL_009A
IL_009A: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_009F: call System.Linq.Enumerable.Where <--------second where call
IL_00A4: stloc.1 // query
IL_00A5: ldloc.1 // query
b__1:
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: cgt
IL_0004: stloc.0 // CS$1$0000
IL_0005: br.s IL_0007
IL_0007: ldloc.0 // CS$1$0000
IL_0008: ret
b__2:
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: clt
IL_0004: stloc.0 // CS$1$0000
IL_0005: br.s IL_0007
IL_0007: ldloc.0 // CS$1$0000
IL_0008: ret
この例は、to where 呼び出しがあり、2 番目の呼び出しが最初の結果を入力として受け取ることを示しています。
そのLinq to Objects
ため、パフォーマンス ヒットが発生します。
パフォーマンスの低下の程度は、データの量と where 句の順序によって異なります。最初の句がフィルタリングされるほど、次の句が処理する必要が少なくなります...私の意見では、ほとんどの場合、パフォーマンスへの影響は大きくありません。
同じ SQL が作成されるため、Linq to SQL
連鎖 Where 句はパフォーマンスに影響しません。