代码放在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