Skip to content

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*/&lt;object&gt; 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*/&lt;object&gt;/*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*/&lt;object&gt;/*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      &quot; 1 &quot; /* 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*/&lt;object&gt;/*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*/&lt;object&gt; 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*/&lt;object&gt;/*1B000001*/::.ctor() /* 0A000011 */
  IL_000f: stloc.2
  IL_0010: ldloc.2

  // 加载变量i,装箱,并调用List&lt;Object&gt;的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*/&lt;object&gt;/*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

  // 将字符串&quot; 1 &quot;赋值给object[0]
  IL_0024: ldloc.3
  IL_0025: ldc.i4.0
  IL_0026: ldstr      &quot; 1 &quot; /* 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*/&lt;object&gt;/*1B000001*/::get_Item(int32) /* 0A000013 */
  IL_0042: stelem.ref

  // 代码【&quot; 1 &quot; + 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