zoukankan      html  css  js  c++  java
  • C#研究系列List<>与ArrayList的几个研究心得及问题(上)

    代码放在https://gist.github.com/921076 上了,看不到的请留言。

    第一个心得,是我看某本书提到,IList用起来要比ArrayList快。

    这里面用到了我上一篇博客提到的高精度计时器(在这里能看到代码 http://sunxiunan.com/?p=1829 )

    在开始定义了两个类。


    //---------------------

    // public class List : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable
    class CFromList : List

    {}

    // public class ArrayList : IList, ICollection, IEnumerable, ICloneable
    class CFromArrayList : ArrayList

    {}

    //---------------------

    List和ArrayList的定义在注释中给出,可以看出来其实都差不多。ArrayList只是多了ICloneable,还少了几个泛型接口继承。

    在后面代码中都用Add方法向list中添加int类型数据,然后通过foreach形式枚举数据,注意!枚举部分的代码是有问题的,我们在(下)中会提到。

    这里还要推荐一个非常棒的工具ILSpy,是sharpdevelop开发的,强烈建议dotnet程序员都下载使用。

    我把ILSpy disassemble出来的C#代码和IL代码分别列在后面。注意对于ArrayList的foreach语句,C#形式的代码与源代码有些差别(79 到96行),编译器加入一个IEnumerator enumerator2 = cFromArrayList.GetEnumerator();本地变量。

    另外使用int num5 = (int)enumerator2.Current;这样访问iterator。而且还加入了IDisposable的finally部分。

    再继续看IL代码部分,对于List形式,IL代码没有box装箱指令,而ArrayList在145行有个box指令,这是性能差别之一。
    但是奇怪的是,在枚举部分,ILSpy生成的(以及ILDasm)IL代码,对于ArrayList和List而言,基本上差别不大,一样也有对 MoveNext和Current以及IDisposable接口的调用。

    只不过ArrayList多出unbox和box的指令。

    运行结果如我们所料,List要比ArrayList快不少。

    但是我们在枚举部分的代码是有问题的,我明天在(下)中会介绍。

        // public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
        class CFromList : List<int>{}
        // public class ArrayList : IList, ICollection, IEnumerable, ICloneable
        class CFromArrayList : ArrayList{}
        public partial class Form1 : Form
        {
            private void button1_Click(object sender, EventArgs e)
            {
                CFromList list1 = new CFromList();
                CFromArrayList list2 = new CFromArrayList();
                ////////////////////////////
                HighResolutionTimer timera = new HighResolutionTimer();
                for (int i = 0; i < 100000; i++)
                {
                    list1.Add(i - 99999);
                }
                Int64 reta = timera.Stop();
                ////////////////////////////
                HighResolutionTimer timerb = new HighResolutionTimer();
                for (int i = 0; i < 100000; i++)
                {
                    list2.Add(i - 99999);
                }
                Int64 retb = timerb.Stop();
                ////////////////////////////
                int index = 0;
                HighResolutionTimer timer1 = new HighResolutionTimer();
                foreach (int elem1 in list1)
                {
                    list1[index++] = elem1 + 99;
                }
                Int64 ret1 = timer1.Stop();
                ////////////////////////////
                index = 0;
                HighResolutionTimer timer2 = new HighResolutionTimer();
                foreach (int elem2 in list2)
                {
                    list2[index++] = elem2 + 99;
                }
                Int64 ret2 = timer2.Stop();
                ////////////////////////////
          }
       }
    ///////////////////////////////////////////////////////
    // result from ILSpy
    CFromList cFromList = new CFromList();
    CFromArrayList cFromArrayList = new CFromArrayList();
    HighResolutionTimer highResolutionTimer = new HighResolutionTimer();
    for (int i = 0; i < 100000; i++)
    {
    cFromList.Add(i - 99999);
    }
    long num = highResolutionTimer.Stop();
    HighResolutionTimer highResolutionTimer2 = new HighResolutionTimer();
    for (int i = 0; i < 100000; i++)
    {
    cFromArrayList.Add(i - 99999);
    }
    long num2 = highResolutionTimer2.Stop();
    int num3 = 0;
    HighResolutionTimer highResolutionTimer3 = new HighResolutionTimer();
    foreach (int current in cFromList)
    {
    cFromList[num3++] = current + 99;
    }
    long num4 = highResolutionTimer3.Stop();
    num3 = 0;
    HighResolutionTimer highResolutionTimer4 = new HighResolutionTimer();
    IEnumerator enumerator2 = cFromArrayList.GetEnumerator();
    try
    {
    while (enumerator2.MoveNext())
    {
    int num5 = (int)enumerator2.Current;
    cFromArrayList[num3++] = num5 + 99;
    }
    }
    finally
    {
    IDisposable disposable = enumerator2 as IDisposable;
    if (disposable != null)
    {
    disposable.Dispose();
    }
    }
    long num6 = highResolutionTimer4.Stop();
    //////////////////////////////////////////////////
    // result from ILSpy IL format
    IL_0000: nop
    IL_0001: newobj instance void WindowsFormsApplication1.CFromList::.ctor()
    IL_0006: stloc.0
    IL_0007: newobj instance void WindowsFormsApplication1.CFromArrayList::.ctor()
    IL_000c: stloc.1
    IL_000d: newobj instance void WindowsFormsApplication1.HighResolutionTimer::.ctor()
    IL_0012: stloc.2
    IL_0013: ldc.i4.0
    IL_0014: stloc.3
    IL_0015: br.s IL_002b
    // loop start (head: IL_002b)
    IL_0017: nop
    IL_0018: ldloc.0
    IL_0019: ldloc.3
    IL_001a: ldc.i4 99999
    IL_001f: sub
    IL_0020: callvirt instance void [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
    IL_0025: nop
    IL_0026: nop
    IL_0027: ldloc.3
    IL_0028: ldc.i4.1
    IL_0029: add
    IL_002a: stloc.3
    IL_002b: ldloc.3
    IL_002c: ldc.i4 100000
    IL_0031: clt
    IL_0033: stloc.s 17
    IL_0035: ldloc.s 17
    IL_0037: brtrue.s IL_0017
    // end loop
    IL_0039: ldloc.2
    IL_003a: callvirt instance int64 WindowsFormsApplication1.HighResolutionTimer::Stop()
    IL_003f: stloc.s 4
    IL_0041: newobj instance void WindowsFormsApplication1.HighResolutionTimer::.ctor()
    IL_0046: stloc.s 5
    IL_0048: ldc.i4.0
    IL_0049: stloc.3
    IL_004a: br.s IL_0065
    // loop start (head: IL_0065)
    IL_004c: nop
    IL_004d: ldloc.1
    IL_004e: ldloc.3
    IL_004f: ldc.i4 99999
    IL_0054: sub
    IL_0055: box int32
    IL_005a: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
    IL_005f: pop
    IL_0060: nop
    IL_0061: ldloc.3
    IL_0062: ldc.i4.1
    IL_0063: add
    IL_0064: stloc.3
    IL_0065: ldloc.3
    IL_0066: ldc.i4 100000
    IL_006b: clt
    IL_006d: stloc.s 17
    IL_006f: ldloc.s 17
    IL_0071: brtrue.s IL_004c
    // end loop
    IL_0073: ldloc.s 5
    IL_0075: callvirt instance int64 WindowsFormsApplication1.HighResolutionTimer::Stop()
    IL_007a: stloc.s 6
    IL_007c: ldc.i4.0
    IL_007d: stloc.s 7
    IL_007f: newobj instance void WindowsFormsApplication1.HighResolutionTimer::.ctor()
    IL_0084: stloc.s 8
    IL_0086: nop
    IL_0087: ldloc.0
    IL_0088: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
    IL_008d: stloc.s 18
    .try {
    IL_008f: br.s IL_00af
    // loop start (head: IL_00af)
    IL_0091: ldloca.s 18
    IL_0093: call instance !0 [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
    IL_0098: stloc.s 9
    IL_009a: nop
    IL_009b: ldloc.0
    IL_009c: ldloc.s 7
    IL_009e: dup
    IL_009f: ldc.i4.1
    IL_00a0: add
    IL_00a1: stloc.s 7
    IL_00a3: ldloc.s 9
    IL_00a5: ldc.i4.s 99
    IL_00a7: add
    IL_00a8: callvirt instance void [mscorlib]System.Collections.Generic.List`1<int32>::set_Item(int32, !0)
    IL_00ad: nop
    IL_00ae: nop
    IL_00af: ldloca.s 18
    IL_00b1: call instance bool [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
    IL_00b6: stloc.s 17
    IL_00b8: ldloc.s 17
    IL_00ba: brtrue.s IL_0091
    // end loop
    IL_00bc: leave.s IL_00cd
    } // end .try
    finally {
    IL_00be: ldloca.s 18
    IL_00c0: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
    IL_00c6: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    IL_00cb: nop
    IL_00cc: endfinally
    } // end handler
    IL_00cd: nop
    IL_00ce: ldloc.s 8
    IL_00d0: callvirt instance int64 WindowsFormsApplication1.HighResolutionTimer::Stop()
    IL_00d5: stloc.s 10
    IL_00d7: ldc.i4.0
    IL_00d8: stloc.s 7
    IL_00da: newobj instance void WindowsFormsApplication1.HighResolutionTimer::.ctor()
    IL_00df: stloc.s 11
    IL_00e1: nop
    IL_00e2: ldloc.1
    IL_00e3: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()
    IL_00e8: stloc.s 19
    .try {
    IL_00ea: br.s IL_0114
    // loop start (head: IL_0114)
    IL_00ec: ldloc.s 19
    IL_00ee: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
    IL_00f3: unbox.any int32
    IL_00f8: stloc.s 12
    IL_00fa: nop
    IL_00fb: ldloc.1
    IL_00fc: ldloc.s 7
    IL_00fe: dup
    IL_00ff: ldc.i4.1
    IL_0100: add
    IL_0101: stloc.s 7
    IL_0103: ldloc.s 12
    IL_0105: ldc.i4.s 99
    IL_0107: add
    IL_0108: box int32
    IL_010d: callvirt instance void [mscorlib]System.Collections.ArrayList::set_Item(int32, object)
    IL_0112: nop
    IL_0113: nop
    IL_0114: ldloc.s 19
    IL_0116: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    IL_011b: stloc.s 17
    IL_011d: ldloc.s 17
    IL_011f: brtrue.s IL_00ec
    // end loop
    IL_0121: leave.s IL_0140
    } // end .try
    finally {
    IL_0123: ldloc.s 19
    IL_0125: isinst class [mscorlib]System.IDisposable
    IL_012a: stloc.s 20
    IL_012c: ldloc.s 20
    IL_012e: ldnull
    IL_012f: ceq
    IL_0131: stloc.s 17
    IL_0133: ldloc.s 17
    IL_0135: brtrue.s IL_013f
    IL_0137: ldloc.s 20
    IL_0139: callvirt instance void [mscorlib]System.IDisposable::Dispose()
    IL_013e: nop
    IL_013f: endfinally
    } // end handler
    IL_0140: nop
    IL_0141: ldloc.s 11
    IL_0143: callvirt instance int64 WindowsFormsApplication1.HighResolutionTimer::Stop()
    IL_0148: stloc.s 13


  • 相关阅读:
    asp.net mvc上传头像加剪裁功能
    CSS基础部分总结
    Web前端之初学CSS
    JavaScript中的new操作符的原理解析
    JS常用数组API汇总
    【NOIP2020提高B组模拟11.26】卡常题
    【NOIP2020提高B组模拟11.26】逗气
    CSP-J/S总结
    计数题
    浅谈线段树——基础篇
  • 原文地址:https://www.cnblogs.com/lua5/p/2017644.html
Copyright © 2011-2022 走看看