程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 再談C#的裝箱和拆箱

再談C#的裝箱和拆箱

編輯:C#入門知識

上一篇寫了一下裝箱拆箱的定義和IL分析,這一篇我們看下使用泛型和不使用泛型引發裝箱拆箱的情況

1. 使用非泛型集合時引發的裝箱和拆箱操作

看下面的一段代碼:

1 var array = new ArrayList(); 

2 array.Add(1); 

3 array.Add(2); 

4   

5 foreach (int value in array) 

6 { 

7 Console.WriteLine(“value is {0}”,value); 

8 }

代碼聲明了一個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#代碼如下:

01 using System; 

02 using System.Collections; 

03 using System.Collections.Generic; 

04   

05 namespace boxOrUnbox 

06 { 

07     class Program 

08     { 

09         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代碼如下:

001 .class private auto ansi beforefieldinit boxOrUnbox.Program 

002     extends [mscorlib]System.Object 

003 { 

004     // Methods 

005     .method private hidebysig static 

006         void Main ( 

007             string[] args 

008         ) cil managed  

009     { 

010         // Method begins at RVA 0x2050 

011         // Code size 2 (0x2) 

012         .maxstack 8 

013         .entrypoint 

014   

015         IL_0000: nop 

016         IL_0001: ret 

017     } // end of method Program::Main 

018   

019     .method private hidebysig static 

020         void Box () cil managed  

021     { 

022         // Method begins at RVA 0x2054 

023         // Code size 10 (0xa) 

024         .maxstack 1 

025         .locals init ( 

026             [0] object objValue 

027         ) 

028   

029         IL_0000: nop 

030         IL_0001: ldc.i4.s 9 

031         IL_0003: box [mscorlib]System.Int32 

032         IL_0008: stloc.0 

033         IL_0009: ret 

034     } // end of method Program::Box 

035   

036     .method private hidebysig static 

037         void Unbox () cil managed  

038     { 

039         // Method begins at RVA 0x206c 

040         // Code size 16 (0x10) 

041         .maxstack 1 

042         .locals init ( 

043             [0] object objValue, 

044             [1] int32 'value'

045         ) 

046   

047         IL_0000: nop 

048         IL_0001: ldc.i4.4 

049         IL_0002: box [mscorlib]System.Int32 

050         IL_0007: stloc.0 

051         IL_0008: ldloc.0 

052         IL_0009: unbox.any [mscorlib]System.Int32 

053         IL_000e: stloc.1 

054         IL_000f: ret 

055     } // end of method Program::Unbox 

056   

057     .method private hidebysig static 

058         void LookatArrayList () cil managed  

059     { 

060         // Method begins at RVA 0x2088 

061         // Code size 114 (0x72) 

062         .maxstack 2 

063         .locals init ( 

064             [0] class [mscorlib]System.Collections.ArrayList 'array', 

065             [1] int32 'value', 

066             [2] class [mscorlib]System.Collections.IEnumerator CS$5$0000, 

067             [3] bool CS$4$0001, 

068             [4] class [mscorlib]System.IDisposable CS$0$0002 

069         ) 

070   

071         IL_0000: nop 

072         IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor() 

073         IL_0006: stloc.0 

074         IL_0007: ldloc.0 

075         IL_0008: ldc.i4.1 

076         IL_0009: box [mscorlib]System.Int32 

077         IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 

078         IL_0013: pop 

079         IL_0014: ldloc.0 

080         IL_0015: ldc.i4.2 

081         IL_0016: box [mscorlib]System.Int32 

082         IL_001b: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 

083         IL_0020: pop 

084         IL_0021: nop 

085         IL_0022: ldloc.0 

086         IL_0023: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator() 

087         IL_0028: stloc.2 

088         .try

089         { 

090             IL_0029: br.s IL_004a 

091             // loop start (head: IL_004a) 

092                 IL_002b: ldloc.2 

093                 IL_002c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current() 

094                 IL_0031: unbox.any [mscorlib]System.Int32 

095                 IL_0036: stloc.1 

096                 IL_0037: nop 

097                 IL_0038: ldstr "value is {0}"

098                 IL_003d: ldloc.1 

099                 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

  
摘自:玉開的技術博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved