对数组或IEnumerable求和

时间:2017-12-29 12:30:48

标签: c# .net linq

我有这样的虚拟代码:

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的版本

更好

0 个答案:

没有答案