盒装值类型与对象中的实际值类型具有相同的地址吗?

时间:2013-05-21 16:59:31

标签: c# .net clr unboxing

来自MSDN unbox

  1. 将对象引用推入堆栈。
  2. 对象引用从堆栈中弹出,并取消装箱到值类型指针。
  3. 值类型指针被压入堆栈。
  4. 在这种情况下,对象引用是否与值类型指针相同? (两个值都是堆中值类型的地址,因为值类型是对象中唯一的成员)?

    例如,一个元素数组:数组的地址与数组的第一个元素的地址相同。

    void Main()
    {
        int[] test = new []{1};
        unsafe
        {
            fixed (int* x = test)
            {
                fixed (int* y = &test[0])
                {
                    Console.WriteLine((int)x);
                    Console.WriteLine((int)y); // They are equal
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:3)

  

为什么需要取消装入值类型指针?

通过280Z28编辑:unbox指令生成一个指向数据的指针,以便根据以下内容实现(潜在)运行时性能优势:

  

ECMA 335 PartitionIII§4.32(摘录):

     

box不同,unbox需要复制值类型才能在对象中使用,unbox.any 需要从对象复制值类型。通常,它只是计算已装箱对象内部已存在的值类型的地址。

添加泛型类型时,{I}指令已添加到CIL。与unbox不同,此指令将值本身放在堆栈上,而不是指向值的指针。

结束280Z28

  

在这种情况下,对象引用是否与值类型指针相同?

没有。对象引用是指对象。值类型指针指向一个值。

想象一下,你有一张纸,上面有12号。你把那张纸放在一个盒子里,然后把盒子放在仓库里。这张纸的位置显然与盒子的位置相关,但它与盒子的位置不是相同。托管引用是框的位置。值类型指针是纸张的位置。仓库是托管堆。

也许这会有所帮助。将盒装int视为int[],其中包含一个元素。 数组的位置与数组第一个元素的位置不同,对吧?拆箱实际上是取消引用数组。

  

两个值都是堆中值类型的地址吗?

没有。一个值是对对象的引用。另一个是指向值类型的托管指针。

  

A行或B行是否创建了m的新副本(抽象地用IL,而不是机器代码)?

我不能为我的生活理解你在这个问题上想要提出的问题。