C# 装箱几次?
🏷️ C#
下面的代码装箱几次?
csharp
using System;
using System.Collections.Generic;
namespace BoxSample
{
class Program
{
static void Main(string args)
{
int i = 5;
Object o = i;
List<Object> list = new List<Object>();
list.Add(i);
Console.WriteLine(" 1 " + o + i + list[0]);
}
}
}
如果把 List<Object>
改成 List<int>
,装箱几次?
只要看 IL 代码中调用了几次box
指令就能知道执行了几次装箱操作.
下面是上面代码的 IL 代码.
点击查看 IL 代码
.method /*06000001*/ private hidebysig static
void Main(string[] args) cil managed
// SIG: 00 01 01 1D 0E
{
.entrypoint
// 方法在 RVA 0x2050 处开始
// 代码大小 80 (0x50)
.maxstack 4
.locals /*11000001*/ init ([0] int32 i,
[1] object o,
[2] class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object> list,
[3] object[] CS$0$0000)
IL_0000: /* 00 | */ nop
IL_0001: /* 1B | */ ldc.i4.5
IL_0002: /* 0A | */ stloc.0
IL_0003: /* 06 | */ ldloc.0
IL_0004: /* 8C | (01)000013 */ box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0009: /* 0B | */ stloc.1
IL_000a: /* 73 | (0A)000011 */ newobj instance void class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::.ctor() /* 0A000011 */
IL_000f: /* 0C | */ stloc.2
IL_0010: /* 08 | */ ldloc.2
IL_0011: /* 06 | */ ldloc.0
IL_0012: /* 8C | (01)000013 */ box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0017: /* 6F | (0A)000012 */ callvirt instance void class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::Add(!0) /* 0A000012 */
IL_001c: /* 00 | */ nop
IL_001d: /* 1A | */ ldc.i4.4
IL_001e: /* 8D | (01)000001 */ newarr [mscorlib/*23000001*/]System.Object/*01000001*/
IL_0023: /* 0D | */ stloc.3
IL_0024: /* 09 | */ ldloc.3
IL_0025: /* 16 | */ ldc.i4.0
IL_0026: /* 72 | (70)000001 */ ldstr " 1 " /* 70000001 */
IL_002b: /* A2 | */ stelem.ref
IL_002c: /* 09 | */ ldloc.3
IL_002d: /* 17 | */ ldc.i4.1
IL_002e: /* 07 | */ ldloc.1
IL_002f: /* A2 | */ stelem.ref
IL_0030: /* 09 | */ ldloc.3
IL_0031: /* 18 | */ ldc.i4.2
IL_0032: /* 06 | */ ldloc.0
IL_0033: /* 8C | (01)000013 */ box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0038: /* A2 | */ stelem.ref
IL_0039: /* 09 | */ ldloc.3
IL_003a: /* 19 | */ ldc.i4.3
IL_003b: /* 08 | */ ldloc.2
IL_003c: /* 16 | */ ldc.i4.0
IL_003d: /* 6F | (0A)000013 */ callvirt instance !0 class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::get_Item(int32) /* 0A000013 */
IL_0042: /* A2 | */ stelem.ref
IL_0043: /* 09 | */ ldloc.3
IL_0044: /* 28 | (0A)000014 */ call string [mscorlib/*23000001*/]System.String/*01000015*/::Concat(object[]) /* 0A000014 */
IL_0049: /* 28 | (0A)000015 */ call void [mscorlib/*23000001*/]System.Console/*01000016*/::WriteLine(string) /* 0A000015 */
IL_004e: /* 00 | */ nop
IL_004f: /* 2A | */ ret
} // end of method Program::Main
为方便理解,给上面的 IL 代码加了点备注.
点击查看 IL 代码
.method /*06000001*/ private hidebysig static
void Main(string[] args) cil managed
// SIG: 00 01 01 1D 0E
{
.entrypoint
// 方法在 RVA 0x2050 处开始
// 代码大小 80 (0x50)
.maxstack 4
// 这里是本地变量的列表
.locals /*11000001*/ init ([0] int32 i,
[1] object o,
[2] class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object> list,
[3] object[] CS$0$0000)
IL_0000: nop
// 加载int型5到变量i
IL_0001: ldc.i4.5
IL_0002: stloc.0
IL_0003: ldloc.0
// 执行装箱操作并赋值到变量o
IL_0004: box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0009: stloc.1
// 创建object的list
IL_000a: newobj instance void class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::.ctor() /* 0A000011 */
IL_000f: stloc.2
IL_0010: ldloc.2
// 加载变量i,装箱,并调用List<Object>的Add方法(因为参数是Object型,所以需要装箱)
IL_0011: ldloc.0
IL_0012: box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0017: callvirt instance void class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::Add(!0) /* 0A000012 */
// 创建一个object[]数组,长度是4(这个变量不是代码里定义的,是为了后面的System.String.Concat方法自动创建的)
IL_001c: nop
// 这个int型的4就是数组的长度
IL_001d: ldc.i4.4
// 创建新的OObject数组
IL_001e: newarr [mscorlib/*23000001*/]System.Object/*01000001*/
IL_0023: stloc.3
// 将字符串" 1 "赋值给object[0]
IL_0024: ldloc.3
IL_0025: ldc.i4.0
IL_0026: ldstr " 1 " /* 70000001 */
IL_002b: stelem.ref
// 将变量0赋值到object[1]
IL_002c: ldloc.3
IL_002d: ldc.i4.1
IL_002e: ldloc.1
IL_002f: stelem.ref
// 将变量i装箱,并赋值到object[2]
IL_0030: ldloc.3
IL_0031: ldc.i4.2
IL_0032: ldloc.0
IL_0033: box [mscorlib/*23000001*/]System.Int32/*01000013*/
IL_0038: stelem.ref
// 将list[0]赋值到object[3]
IL_0039: ldloc.3
IL_003a: ldc.i4.3
IL_003b: ldloc.2
IL_003c: ldc.i4.0
IL_003d: callvirt instance !0 class [mscorlib/*23000001*/]System.Collections.Generic.List`1/*01000014*/<object>/*1B000001*/::get_Item(int32) /* 0A000013 */
IL_0042: stelem.ref
// 代码【" 1 " + o + i + list[0]】,其实执行的是System.String的Concat(object[])方法
IL_0043: ldloc.3
IL_0044: call string [mscorlib/*23000001*/]System.String/*01000015*/::Concat(object[]) /* 0A000014 */
// 调用System.Console.WriteLine(string)方法
IL_0049: call void [mscorlib/*23000001*/]System.Console/*01000016*/::WriteLine(string) /* 0A000015 */
IL_004e: nop
// return
IL_004f: ret
} // end of method Program::Main