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


转载于:https://www.cnblogs.com/lua5/archive/2011/04/15/2017644.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值