您的位置:首页 > 编程语言 > C#

C#研究系列-List<>与ArrayList的几个研究心得及问题(上)

2011-04-15 23:55 736 查看
代码放在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: