I wrote it in the previous post Definition of boxing and unboxing and IL analysis , in this article, let's look at the case of using generics and not using generics to cause boxing and unboxing
1. Boxing and unboxing operations when using non-generic collections
Look at the following piece of code:
?
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); }
The code declares an ArrayList object, adds two numbers 1, 2 to the ArrayList; then uses foreach to print the elements in the ArrayList to the console.
In this process, two boxing operations and two unboxing operations will occur. Boxing will occur when adding elements of type int to ArrayList, and unboxing will occur when using foreach to enumerate elements of type int in ArrayList. Convert the object type to int type, and perform two boxing operations when executing Console.WriteLine; this piece of code performs 6 boxing and unboxing operations; if the ArrayList has a large number of elements, execute There will be more operations for packing and unpacking.
You can view the boxing and unboxing process by using tools such as ILSpy to view the box and unbox instructions of the IL code
2. The case of using generic collections
Please see the following code:
?
var list = new List<int>(); list.Add(1); list.Add(2); foreach (int value in list) { Console.WriteLine("value is {0}", value); }
The difference between the code and the code in 1 is that the type of the collection uses a generic List instead of an ArrayList; we can also check the boxing and unboxing by looking at the IL code. The above code will only be used in the Console.WriteLine() method. Perform 2 boxing operations, no unboxing operations are required.
It can be seen that generics can avoid unnecessary performance consumption caused by boxing and unboxing; of course, the benefits of generics are more than that, generics can also increase the readability of programs, make programs easier to reuse, and so on.
The C# code used in this article is as follows:
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 }
The IL code of C# is as follows:
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
************ Reprinted: https://www.cnblogs.com/yukaizhao/archive/2004/01/13/csharp_box_unbox_2.html