C# 装箱与拆箱
最近我在采访中遇到的另一个问题是,我是否知道什么是装箱和拆箱。 我解释了值类型在堆栈上,引用类型在堆上。 当一个值被转换为引用类型时,我们称之为装箱,反之亦然 然后他让我计算一下:C# 装箱与拆箱,c#,boxing,unboxing,C#,Boxing,Unboxing,最近我在采访中遇到的另一个问题是,我是否知道什么是装箱和拆箱。 我解释了值类型在堆栈上,引用类型在堆上。 当一个值被转换为引用类型时,我们称之为装箱,反之亦然 然后他让我计算一下: int i = 20; object j = i; j = 50; 什么是i 我搞砸了,说是50,实际上是20。现在我想我明白了为什么,但是当我玩不同的组合时,我惊讶地发现: Object a = 1; // Boxing Object b = a; // referencing the pointer on st
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,现在是。但这根本不是装箱/拆箱的例子,对吗?那么你如何总结这一点呢
装箱/拆箱转换中的值是否会与上述值相同?
b
变量也在引用它),并为新值创建一个新对象,而a
变量将引用该对象
您的第二个示例没有使用拳击是对的。除了解除装箱,您无法访问以任何其他方式装箱的值,因此无法更改装箱的值
装箱时,即使是像
Point
这样的可变结构也无法更改。要访问结构的属性,您必须取消装箱,因此无法就地更改装箱结构。b仍然是1,因为b是仍然指向堆上值为1的对象的引用。a是2,因为您将其分配给堆上的一个值为2的新对象
t2.x是3,因为t和t2是对堆上同一对象的两个不同引用。我认为对您的问题的解装箱的答案是:解装箱转换的结果是一个临时变量(更多详细信息:) 我想你想做的是:
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)-对象
非常简短:装箱意味着创建引用类型的新实例。如果您知道这一点,您就知道创建另一个实例不会改变一个实例
使用
a=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
嗨,谢谢你的回答。请您详细说明一下“拳击仍然保持不变性保证”?感谢kaveMost值类型是不可变的,例如:一个int只能有一个值。如果你改变了值,你实际上是在创建一个新的整型。NET对装箱对象保持这种不变性:如果你给它赋值,你就是在创建一个新的装箱整型。这同样适用于装箱结构。这是完全有意义的。Thanks@grover:什么是不变性保证?任何装箱的值类型都可以通过用C++/CLI编写的可信且可验证的代码轻松地进行自由变异。值类型,如
List.Enumerator
,它实现了可变接口,当装箱时,将表现为可变类类型。很好的解释,现在当您取消装箱时会发生什么?引用类型的新实例是否被销毁?引用类型总是被垃圾收集销毁。因此,当不再引用时,它将被销毁。简短n甜美的回答,非常好。值得注意的是,在C++/CLI中,直接在可信和可验证的代码中修改盒装堆对象没有困难。另请参阅,以获取一般性阅读