Box和UnBox简单对比试验

来源:互联网 发布:linux网卡配置ip地址 编辑:程序博客网 时间:2024/05/17 05:03

虽说使用C#很长时间了,对Box的概念一直没有搞清楚。今天抽时间专门研究了一下,有一些发现。

具体对比过程见下,ildasm代码中有注释说明。基本结论有以下两点:

一 从代码执行过程来看:

1.1 基本数据类型,将SrcValue赋值给Obj,有一个Box动作; Obj赋值给DesValue,有一个UnBox动作。

1.2 string数据类型,将SrcValue赋值给Obj,没有Box动作; 而将Obj赋值给DesValue,有一个强制类型转换。

1.3 自定义class类型,将SrcValue赋值给Obj,没有Box动作; 而将Obj赋值给DesValue,有一个强制类型转换。

 二 从执行结果来看(将SrcValue赋值给Obj,再将Obj赋值给DesValue,再修改SrcValue):

2.1 基本数据类型,修改SrcValue后,DesValue没有变化

2.2 string数据类型,修改SrcValue后,DesValue没有变化

2.3 自定义class类型,修改SrcValue后,DesValue跟随变化

从中可以看出基本数据类型是值传递(即value),string是微软内置类型,和基本数据类型表现一致; 而自定义class型是引用传递(即reference)。

 

 1 基本数据类型(以double为例)

源代码

private static void PlainType( )
{

    double dSrcValue = 1.01;
    object Obj = dSrcValue;
    double dDesValue = (double)Obj;

    System.Console.WriteLine("SrcValue = {0}", dSrcValue);
    System.Console.WriteLine("DesValue = {0}", dDesValue);

    System.Console.ReadKey();
    System.Console.WriteLine("\n");
    dSrcValue = 2.02;
    System.Console.WriteLine("SrcValue = {0}", dSrcValue);
    System.Console.WriteLine("DesValue = {0}", dDesValue);

    System.Console.ReadKey();

 }

static void Main(string[] args)
{
    PlainType();       

}

执行结果:

SrcValue = 1.01
DesValue = 1.01


SrcValue = 2.02
DesValue = 1.01

 

ildasm的代码

.method private hidebysig static void  PlainType() cil managed
{
  // Code size       127 (0x7f)
  .maxstack  2
  .locals init ([0] float64 dSrcValue,
           [1] object Obj,
           [2] float64 dDesValue)      // 变量在栈内存中初始化
  IL_0000:  nop
  IL_0001:  ldc.r8     1.01
  IL_000a:  stloc.0                                                    // 赋值给dSrcValue
  IL_000b:  ldloc.0                                                   // 加载dSrcValue的值
  IL_000c:  box        [mscorlib]System.Double   // 对dSrcValue进行Box处理
  IL_0011:  stloc.1                                                   // 赋值给 Obj
  IL_0012:  ldloc.1                                                         // 加载Obj的值
  IL_0013:  unbox.any  [mscorlib]System.Double   // UnBox 
  IL_0018:  stloc.2                                                         // 赋值给dDesValue  
  IL_0019:  ldstr      "SrcValue = {0}"                          // 加载格式化字符串
  IL_001e:  ldloc.0                                                        // 加载dSrcValue值
  IL_001f:  box        [mscorlib]System.Double         // dSrcValue值Box处理
  IL_0024:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0029:  nop
  IL_002a:  ldstr      "DesValue = {0}"                       // 加载格式化字符串
  IL_002f:  ldloc.2                                                        // 加载dDesValue
  IL_0030:  box        [mscorlib]System.Double
  IL_0035:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_003a:  nop
  IL_003b:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0040:  pop
  IL_0041:  ldstr      "\n"
  IL_0046:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_004b:  nop
  IL_004c:  ldc.r8     2.02
  IL_0055:  stloc.0                                                   // 赋值给dSrcValue
  IL_0056:  ldstr      "SrcValue = {0}"                    // 加载格式化字符串
  IL_005b:  ldloc.0                                                  // 加载dSrcValue值
  IL_005c:  box        [mscorlib]System.Double  // dSrcValue值Box处理
  IL_0061:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0066:  nop
  IL_0067:  ldstr      "DesValue = {0}"                   // 加载格式化字符串
  IL_006c:  ldloc.2                                                   // 加载dDesValue
  IL_006d:  box        [mscorlib]System.Double  // dDesValue Box处理
  IL_0072:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0077:  nop
  IL_0078:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_007d:  pop
  IL_007e:  ret
} // end of method Program::PlainType

2 string类型

源代码:

 private static void StringType()
{
    string SrcValue = "ABC";
    object Obj = SrcValue;
    string DesValue = (string)Obj;

    System.Console.WriteLine("SrcValue = {0}", SrcValue);
    System.Console.WriteLine("DesValue = {0}", DesValue);

    System.Console.ReadKey();
    System.Console.WriteLine("\n");
    SrcValue = "DEF";
    System.Console.WriteLine("SrcValue = {0}", SrcValue);
    System.Console.WriteLine("DesValue = {0}", DesValue);

    System.Console.ReadKey();
}

static void Main(string[] args)
{
    StringType();   

}

执行结果:

SrcValue = ABC
DesValue = ABC


SrcValue = DEF
DesValue = ABC

 

ildasm代码:

.method private hidebysig static void  StringType() cil managed
{
  // Code size       94 (0x5e)
  .maxstack  2
  .locals init ([0] string SrcValue,
           [1] object Obj,
           [2] string DesValue)
  IL_0000:  nop
  IL_0001:  ldstr      "ABC"   // 加载常量字符串"ABC"
  IL_0006:  stloc.0                        // "ABC"赋给SrcValue
  IL_0007:  ldloc.0                       // 加载SrcValue
  IL_0008:  stloc.1                       // "ABC"赋值给Obj
  IL_0009:  ldloc.1                       // 加载Obj 
  IL_000a:  castclass  [mscorlib]System.String         // Obj类型转换为string类型
  IL_000f:  stloc.2                // 转换结果赋值给DesValue
  IL_0010:  ldstr      "SrcValue = {0}"
  IL_0015:  ldloc.0
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)    // 打印字符串SrcValue
  IL_001b:  nop
  IL_001c:  ldstr      "DesValue = {0}"
  IL_0021:  ldloc.2
  IL_0022:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)   // 打印字符串DesValue
  IL_0027:  nop
  IL_0028:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_002d:  pop
  IL_002e:  ldstr      "\n"
  IL_0033:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0038:  nop
  IL_0039:  ldstr      "DEF"
  IL_003e:  stloc.0                            // 常量字符串"DEF"赋值给SrcValue
  IL_003f:  ldstr      "SrcValue = {0}"
  IL_0044:  ldloc.0
  IL_0045:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_004a:  nop
  IL_004b:  ldstr      "DesValue = {0}"
  IL_0050:  ldloc.2
  IL_0051:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0056:  nop
  IL_0057:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_005c:  pop
  IL_005d:  ret
} // end of method Program::StringType

 

3 自定义class类型

源代码

class MyRefClass<T>
    {
        private T m_Value;
        public T Value
        {
            set { m_Value = value; }
        }
        public MyRefClass(T _Value)
        {
            m_Value = _Value;
        }

        public T PrintValue()
        {
            return m_Value;
        }
    }

 

private static void RefClassType()
{
    MyRefClass<double> SrcValue = new MyRefClass<double>(1.01);
    object Obj = SrcValue;
    MyRefClass<double> DesValue = (MyRefClass<double>)Obj;

    System.Console.WriteLine("SrcValue = {0}", SrcValue.PrintValue());
    System.Console.WriteLine("DesValue = {0}", DesValue.PrintValue());

    System.Console.ReadKey();
    System.Console.WriteLine("\n");
    SrcValue.Value = 2.02;
    System.Console.WriteLine("SrcValue = {0}", SrcValue.PrintValue());
    System.Console.WriteLine("DesValue = {0}", DesValue.PrintValue());

    System.Console.ReadKey();
}

static void Main(string[] args)
{

    RefClassType();

}

执行结果:

SrcValue = 1.01
DesValue = 1.01


SrcValue = 2.02
DesValue = 2.02

 

ildasm代码:

.method private hidebysig static void  RefClassType() cil managed
{
  // Code size       153 (0x99)
  .maxstack  2
  .locals init ([0] class Boxing.MyRefClass`1<float64> SrcValue,
           [1] object Obj,
           [2] class Boxing.MyRefClass`1<float64> DesValue)
  IL_0000:  nop
  IL_0001:  ldc.r8     1.01
  IL_000a:  newobj     instance void class Boxing.MyRefClass`1<float64>::.ctor(!0)  // 创建MyRefClass对象
  IL_000f:  stloc.0                         // 赋值给SrcValue
  IL_0010:  ldloc.0
  IL_0011:  stloc.1                       // 赋值给Obj
  IL_0012:  ldloc.1
  IL_0013:  castclass  class Boxing.MyRefClass`1<float64> // Obj类型转换
  IL_0018:  stloc.2                                                                           // 赋值给DesValue
  IL_0019:  ldstr      "SrcValue = {0}"
  IL_001e:  ldloc.0
  IL_001f:  callvirt   instance !0 class Boxing.MyRefClass`1<float64>::PrintValue()
  IL_0024:  box        [mscorlib]System.Double
  IL_0029:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_002e:  nop
  IL_002f:  ldstr      "DesValue = {0}"
  IL_0034:  ldloc.2
  IL_0035:  callvirt   instance !0 class Boxing.MyRefClass`1<float64>::PrintValue()
  IL_003a:  box        [mscorlib]System.Double
  IL_003f:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0044:  nop
  IL_0045:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_004a:  pop
  IL_004b:  ldstr      "\n"
  IL_0050:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0055:  nop
  IL_0056:  ldloc.0
  IL_0057:  ldc.r8     2.02
  IL_0060:  callvirt   instance void class Boxing.MyRefClass`1<float64>::set_Value(!0)
  IL_0065:  nop
  IL_0066:  ldstr      "SrcValue = {0}"
  IL_006b:  ldloc.0
  IL_006c:  callvirt   instance !0 class Boxing.MyRefClass`1<float64>::PrintValue()
  IL_0071:  box        [mscorlib]System.Double
  IL_0076:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_007b:  nop
  IL_007c:  ldstr      "DesValue = {0}"
  IL_0081:  ldloc.2
  IL_0082:  callvirt   instance !0 class Boxing.MyRefClass`1<float64>::PrintValue()
  IL_0087:  box        [mscorlib]System.Double
  IL_008c:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0091:  nop
  IL_0092:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0097:  pop
  IL_0098:  ret
} // end of method Program::RefClassType

 

原创粉丝点击