我有这样的虚拟代码:
public int SAdd2(IEnumerable < int > a)
{
var sum = a.Sum();
var s = a.Where(x = > x < 4).Sum();
return sum;
}
Resharper让我把它改成:
public int SAdd(IEnumerable < int > a)
{
var enumerable = a as int[] ? ? a.ToArray();
var sum = enumerable.Sum();
var s = enumerable.Where(x = > x < 4).Sum();
return sum;
}
或与List<int>
相同而不是数组。
由于:
可能多次枚举IEnumerable
我在MS Sources代码中找到了可枚举
中Sum
的代码
public static int Sum(this IEnumerable < int > source)
{
if (source == null) throw Error.ArgumentNull("source");
int sum = 0;
checked
{
foreach(int v in source) sum += v;
}
return sum;
}
在网站sharplab.io我生成IL代码:
.method public hidebysig
instance int32 SAdd(
class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > a
) cil managed
{
// Method begins at RVA 0x2054
// Code size 67 (0x43)
.maxstack 3
.locals init(
[0] int32
)
IL_0000: ldarg.1
IL_0001: isinst int32[]
IL_0006: dup
IL_0007: brtrue.s IL_0010
IL_0009: pop
IL_000a: ldarg.1
IL_000b: call !! 0[][System.Core] System.Linq.Enumerable::ToArray < int32 > (class[mscorlib] System.Collections.Generic.IEnumerable` 1 < !! 0 > )
IL_0010: dup
IL_0011: call int32[System.Core] System.Linq.Enumerable::Sum(class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > )
IL_0016: stloc.0
IL_0017: ldsfld class[mscorlib] System.Func` 2 < int32,
bool > C / '<>c'::'<>9__1_0'
IL_001c: dup
IL_001d: brtrue.s IL_0036
IL_001f: pop
IL_0020: ldsfld class C / '<>c'
C / '<>c'::'<>9'
IL_0025: ldftn instance bool C / '<>c'::'<SAdd>b__1_0' (int32)
IL_002b: newobj instance void class[mscorlib] System.Func` 2 < int32,
bool > ::.ctor(object, native int)
IL_0030: dup
IL_0031: stsfld class[mscorlib] System.Func` 2 < int32,
bool > C / '<>c'::'<>9__1_0'
IL_0036: call class[mscorlib] System.Collections.Generic.IEnumerable` 1 < !! 0 > [System.Core] System.Linq.Enumerable::Where < int32 > (class[mscorlib] System.Collections.Generic.IEnumerable` 1 < !! 0 > , class[mscorlib] System.Func` 2 < !! 0, bool > )
IL_003b: call int32[System.Core] System.Linq.Enumerable::Sum(class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > )
IL_0040: pop
IL_0041: ldloc.0
IL_0042: ret
} // end of method C::SAdd
.method public hidebysig
instance int32 SAdd2(
class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > a
) cil managed
{
// Method begins at RVA 0x20a3
// Code size 50 (0x32)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call int32[System.Core] System.Linq.Enumerable::Sum(class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > )
IL_0006: ldarg.1
IL_0007: ldsfld class[mscorlib] System.Func` 2 < int32,
bool > C / '<>c'::'<>9__2_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class C / '<>c'
C / '<>c'::'<>9'
IL_0015: ldftn instance bool C / '<>c'::'<SAdd2>b__2_0' (int32)
IL_001b: newobj instance void class[mscorlib] System.Func` 2 < int32,
bool > ::.ctor(object, native int)
IL_0020: dup
IL_0021: stsfld class[mscorlib] System.Func` 2 < int32,
bool > C / '<>c'::'<>9__2_0'
IL_0026: call class[mscorlib] System.Collections.Generic.IEnumerable` 1 < !! 0 > [System.Core] System.Linq.Enumerable::Where < int32 > (class[mscorlib] System.Collections.Generic.IEnumerable` 1 < !! 0 > , class[mscorlib] System.Func` 2 < !! 0, bool > )
IL_002b: call int32[System.Core] System.Linq.Enumerable::Sum(class[mscorlib] System.Collections.Generic.IEnumerable` 1 < int32 > )
IL_0030: pop
IL_0031: ret
} // end of method C::SAdd2
在这两种情况下称为相同的功能:
call int32 [System.Core]System.Linq.Enumerable::Sum(class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>)
为什么带有数组或List
的版本比带有IEnumerable
的版本