拳击与拆箱

时间:2009-04-18 21:10:18

标签: c# boxing unboxing

我最近的另一个C#面试问题是,如果我知道Boxing和Unboxing是什么。 我解释了堆上的值类型和Heap上的引用类型。 当一个值被强制转换为引用类型时,我们将其称为装箱,反之亦然。

然后他让我计算一下:

int i = 20;
object j = i;
j = 50;

什么是i

我把它搞砸了50,说实际上是20.现在我想明白为什么,但是当我玩不同的组合时,我很惊讶地看到了这一点:

Object a = 1; // Boxing
Object b = a; // referencing the pointer on stack to both objects on heap
a = 2; // Boxing

我也期待看到b == 2,但事实并非如此?是因为第二次拳击会破坏并替换堆上的整个a对象吗?

因为如果我这样做,那很好:

public class TT
{
    public int x;
}

TT t = new TT();
t.x = 1;
TT t2 = new TT();
t2.x = 2;
t = t2;
t.x = 3;

什么是t2.x?它应该是3,它是。但这不是拳击/拆箱的例子,这是正确的吗?那你怎么总结这个呢?

上述装箱/拆箱转换中的值是否会相同?

6 个答案:

答案 0 :(得分:8)

非常简短:装箱意味着创建引用类型的新实例。如果你知道这一点,你就会明白一个实例不会因创建另一个实例而改变。

使用a = 2进行的操作不会更改“框”中的值,而是创建引用类型的新实例。那么为什么要改变其他什么呢?

答案 1 :(得分:5)

  1. 你是对的,第二个任务取代了第一个。它不会更改盒装值。

  2. 你的例子没有使用拳击。值(int)存储为int而不是盒装。

  3. 不,拳击仍保持不变性保证。

答案 2 :(得分:2)

  

我期待看到b == 2,   但事实并非如此?是因为   第二次拳击摧毁并取代   堆上的整个(a)对象?

不,不完全是。它将对象保留在堆上(因为b变量也引用它)并为新值创建一个新对象,a变量将引用该对象。

你是对的,你的第二个例子不使用拳击。您无法以取消装箱的方式访问以其他方式装箱的值,因此无法更改装箱值。

在装箱时,甚至不能更改像Point这样的可变结构。要访问结构的属性,必须将其取消装箱,这样就无法更改盒装结构。

答案 3 :(得分:2)

这是支持Stefan评论的另一个有趣变体:

        int i = 2;
        object a = i; // Boxing
        object b = a; // Referencing same address on heap as 'a', b == a

        b = i; // New boxing on heap with reference new address, b != a

答案 4 :(得分:1)

b仍为1,因为b是仍然指向堆上的对象的引用,其值为1.a为2,因为您将其分配给堆上的新对象,值为2.

t2.x是3,因为t和t2是对堆上同一对象的两个不同引用。

答案 5 :(得分:0)

我认为解决问题的答案是:取消装箱转换的结果是一个临时变量(更多细节:link)。

我认为你试图做某事:

object a = new Point(10,10);
object b = new Point(20,20);
a = b;

((Point) b).X = 30; //after this operation also a.X should be 30

以上代码无法编译 - 上面链接中的详细信息,我认为这是您问题的答案:

  

我期待看到b == 2,   但事实并非如此?是因为   第二次拳击摧毁并取代   堆上的整个(a)对象?