深入理解C#的装箱和拆箱(二)

上一篇写了一下装箱拆箱的定义和IL分析,这一篇我们看下使用泛型和不使用泛型引发装箱拆箱的情况

1.使用非泛型集合时引发的装箱和拆箱操作 

看下面的一段代码:

1
2
3
4
5
6
7
8
var array = new ArrayList();
array.Add(1);
array.Add(2);
 
foreach (int value in array)
{
Console.WriteLine(“value is {0}”,value);
}

代码声明了一个ArrayList对象,向ArrayList中添加两个数字1,2;然后使用foreach将ArrayList中的元素打印到控制台。

在这个过程中会发生两次装箱操作和两次拆箱操作,在向ArrayList中添加int类型元素时会发生装箱,在使用foreach枚举ArrayList中的int类型元素时会发生拆箱操作,将object类型转换成int类型,在执行到Console.WriteLine时,还会执行两次的装箱操作;这一段代码执行了6次的装箱和拆箱操作;如果ArrayList的元素个数很多,执行装箱拆箱的操作会更多。

你可以通过使用ILSpy之类的工具查看IL代码的box,unbox指令查看装箱和拆箱的过程

2.使用泛型集合的情况

请看如下代码:

var list = new List<int>();
list.Add(1);
list.Add(2);
 
foreach (int value in list)
{
Console.WriteLine("value is {0}", value);
}

代码和1中的代码的差别在于集合的类型使用了泛型的List,而非ArrayList;我们同样可以通过查看IL代码查看装箱拆箱的情况,上述代码只会在Console.WriteLine()方法时执行2次装箱操作,不需要拆箱操作。

可以看出泛型可以避免装箱拆箱带来的不必要的性能消耗;当然泛型的好处不止于此,泛型还可以增加程序的可读性,使程序更容易被复用等等。

本文使用的C#代码如下:

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4  
 5 namespace boxOrUnbox
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //do nothing
12         }
13  
14         static void Box()
15         {
16             object objValue = 9;
17         }
18  
19         static void Unbox()
20         {
21             object objValue = 4;
22             int value = (int)objValue;
23         }
24  
25         static void LookatArrayList()
26         {
27             var array = new ArrayList();
28             array.Add(1);
29             array.Add(2);
30  
31             foreach (int value in array)
32             {
33                 Console.WriteLine("value is {0}", value);
34             }
35         }
36  
37         static void LookatGenericList()
38         {
39             var list = new List<int>();
40             list.Add(1);
41             list.Add(2);
42  
43             foreach (int value in list)
44             {
45                 Console.WriteLine("value is {0}", value);
46             }
47         }
48     }
49 }

C#的IL代码如下:

  1 .class private auto ansi beforefieldinit boxOrUnbox.Program
  2     extends [mscorlib]System.Object
  3 {
  4     // Methods
  5     .method private hidebysig static
  6         void Main (
  7             string[] args
  8         ) cil managed
  9     {
 10         // Method begins at RVA 0x2050
 11         // Code size 2 (0x2)
 12         .maxstack 8
 13         .entrypoint
 14  
 15         IL_0000: nop
 16         IL_0001: ret
 17     } // end of method Program::Main
 18  
 19     .method private hidebysig static
 20         void Box () cil managed
 21     {
 22         // Method begins at RVA 0x2054
 23         // Code size 10 (0xa)
 24         .maxstack 1
 25         .locals init (
 26             [0] object objValue
 27         )
 28  
 29         IL_0000: nop
 30         IL_0001: ldc.i4.s 9
 31         IL_0003: box [mscorlib]System.Int32
 32         IL_0008: stloc.0
 33         IL_0009: ret
 34     } // end of method Program::Box
 35  
 36     .method private hidebysig static
 37         void Unbox () cil managed
 38     {
 39         // Method begins at RVA 0x206c
 40         // Code size 16 (0x10)
 41         .maxstack 1
 42         .locals init (
 43             [0] object objValue,
 44             [1] int32 'value'
 45         )
 46  
 47         IL_0000: nop
 48         IL_0001: ldc.i4.4
 49         IL_0002: box [mscorlib]System.Int32
 50         IL_0007: stloc.0
 51         IL_0008: ldloc.0
 52         IL_0009: unbox.any [mscorlib]System.Int32
 53         IL_000e: stloc.1
 54         IL_000f: ret
 55     } // end of method Program::Unbox
 56  
 57     .method private hidebysig static
 58         void LookatArrayList () cil managed
 59     {
 60         // Method begins at RVA 0x2088
 61         // Code size 114 (0x72)
 62         .maxstack 2
 63         .locals init (
 64             [0] class [mscorlib]System.Collections.ArrayList 'array',
 65             [1] int32 'value',
 66             [2] class [mscorlib]System.Collections.IEnumerator CS$5$0000,
 67             [3] bool CS$4$0001,
 68             [4] class [mscorlib]System.IDisposable CS$0$0002
 69         )
 70  
 71         IL_0000: nop
 72         IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
 73         IL_0006: stloc.0
 74         IL_0007: ldloc.0
 75         IL_0008: ldc.i4.1
 76         IL_0009: box [mscorlib]System.Int32
 77         IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
 78         IL_0013: pop
 79         IL_0014: ldloc.0
 80         IL_0015: ldc.i4.2
 81         IL_0016: box [mscorlib]System.Int32
 82         IL_001b: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
 83         IL_0020: pop
 84         IL_0021: nop
 85         IL_0022: ldloc.0
 86         IL_0023: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()
 87         IL_0028: stloc.2
 88         .try
 89         {
 90             IL_0029: br.s IL_004a
 91             // loop start (head: IL_004a)
 92                 IL_002b: ldloc.2
 93                 IL_002c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
 94                 IL_0031: unbox.any [mscorlib]System.Int32
 95                 IL_0036: stloc.1
 96                 IL_0037: nop
 97                 IL_0038: ldstr "value is {0}"
 98                 IL_003d: ldloc.1
 99                 IL_003e: box [mscorlib]System.Int32
100                 IL_0043: call void [mscorlib]System.Console::WriteLine(string, object)
101                 IL_0048: nop
102                 IL_0049: nop
103  
104                 IL_004a: ldloc.2
105                 IL_004b: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
106                 IL_0050: stloc.3
107                 IL_0051: ldloc.3
108                 IL_0052: brtrue.s IL_002b
109             // end loop
110  
111             IL_0054: leave.s IL_0070
112         } // end .try
113         finally
114         {
115             IL_0056: ldloc.2
116             IL_0057: isinst [mscorlib]System.IDisposable
117             IL_005c: stloc.s CS$0$0002
118             IL_005e: ldloc.s CS$0$0002
119             IL_0060: ldnull
120             IL_0061: ceq
121             IL_0063: stloc.3
122             IL_0064: ldloc.3
123             IL_0065: brtrue.s IL_006f
124  
125             IL_0067: ldloc.s CS$0$0002
126             IL_0069: callvirt instance void [mscorlib]System.IDisposable::Dispose()
127             IL_006e: nop
128  
129             IL_006f: endfinally
130         } // end handler
131  
132         IL_0070: nop
133         IL_0071: ret
134     } // end of method Program::LookatArrayList
135  
136     .method private hidebysig static
137         void LookatGenericList () cil managed
138     {
139         // Method begins at RVA 0x2118
140         // Code size 90 (0x5a)
141         .maxstack 2
142         .locals init (
143             [0] class [mscorlib]System.Collections.Generic.List`1<int32> list,
144             [1] int32 'value',
145             [2] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32> CS$5$0000,
146             [3] bool CS$4$0001
147         )
148  
149         IL_0000: nop
150         IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
151         IL_0006: stloc.0
152         IL_0007: ldloc.0
153         IL_0008: ldc.i4.1
154         IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
155         IL_000e: nop
156         IL_000f: ldloc.0
157         IL_0010: ldc.i4.2
158         IL_0011: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
159         IL_0016: nop
160         IL_0017: nop
161         IL_0018: ldloc.0
162         IL_0019: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
163         IL_001e: stloc.2
164         .try
165         {
166             IL_001f: br.s IL_003c
167             // loop start (head: IL_003c)
168                 IL_0021: ldloca.s CS$5$0000
169                 IL_0023: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
170                 IL_0028: stloc.1
171                 IL_0029: nop
172                 IL_002a: ldstr "value is {0}"
173                 IL_002f: ldloc.1
174                 IL_0030: box [mscorlib]System.Int32
175                 IL_0035: call void [mscorlib]System.Console::WriteLine(string, object)
176                 IL_003a: nop
177                 IL_003b: nop
178  
179                 IL_003c: ldloca.s CS$5$0000
180                 IL_003e: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
181                 IL_0043: stloc.3
182                 IL_0044: ldloc.3
183                 IL_0045: brtrue.s IL_0021
184             // end loop
185  
186             IL_0047: leave.s IL_0058
187         } // end .try
188         finally
189         {
190             IL_0049: ldloca.s CS$5$0000
191             IL_004b: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
192             IL_0051: callvirt instance void [mscorlib]System.IDisposable::Dispose()
193             IL_0056: nop
194             IL_0057: endfinally
195         } // end handler
196  
197         IL_0058: nop
198         IL_0059: ret
199     } // end of method Program::LookatGenericList
200  
201     .method public hidebysig specialname rtspecialname
202         instance void .ctor () cil managed
203     {
204         // Method begins at RVA 0x2190
205         // Code size 7 (0x7)
206         .maxstack 8
207  
208         IL_0000: ldarg.0
209         IL_0001: call instance void [mscorlib]System.Object::.ctor()
210         IL_0006: ret
211     } // end of method Program::.ctor
212  
213 } // end of class boxOrUnbox.Program

***********转摘:https://www.cnblogs.com/yukaizhao/archive/2004/01/13/csharp_box_unbox_2.html

原文地址:https://www.cnblogs.com/linybo/p/13679627.html