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 调用,第二个接收第一个结果作为输入。
因此,Linq to Objects
性能会受到影响。
性能恶化的程度取决于数据量和 where 子句的顺序,第一个子句过滤的越多,下一个子句必须操作的越少,依此类推……在我看来,在大多数情况下性能影响不会很大。
In Linq to SQL
Chaining Where 子句对性能没有影响,因为将创建相同的 SQL。