C# 拳击……我做对了吗?

C# 拳击……我做对了吗?,c#,.net,boxing,C#,.net,Boxing,可能重复: 嗨, 据我了解: 当我将value类型的数据分配给(reference)类型的对象变量时,它被装箱,结果不是实际的引用,因为它指向存储在堆上的值的副本。是这样吗? 谢谢,不太好。(一开始我误读了你的帖子。) 结果是一个真正的引用-但它没有引用原始变量。它引用堆上的一个对象,其中包含装箱时变量所持有的值的副本。特别是,更改变量的值不会更改框中的值: int i = 10; object o = i; i = 11; Console.WriteLine(o); // Prints 10

可能重复:

嗨, 据我了解: 当我将value类型的数据分配给(reference)类型的对象变量时,它被装箱,结果不是实际的引用,因为它指向存储在堆上的值的副本。是这样吗? 谢谢,不太好。(一开始我误读了你的帖子。)

结果是一个真正的引用-但它没有引用原始变量。它引用堆上的一个对象,其中包含装箱时变量所持有的值的副本。特别是,更改变量的值不会更改框中的值:

int i = 10;
object o = i;
i = 11;
Console.WriteLine(o); // Prints 10, not 11
C#不允许您直接访问框中的值-您只能通过拆箱并复制来获取它。另一方面,C++/CLI允许单独访问甚至更改框中的值。(您仍然可以使用C#潜在地更改框中的值-例如,如果值类型实现了某些接口,并且接口方法改变了该值。)

通常,导致装箱的引用类型是“object”,但它可能是值类型实现的某个接口,或者只是
System.ValueType

这可能会对您有所帮助

int i = 1;
object o = i;   // boxing on the heap
int j = (int) o;    // unboxing to the stack

是对于第一部分,将值类型指定给引用变量将使用装箱。 基本上,在需要引用类型的任何上下文中使用值类型都会将值框起来


是的,(在当前实现中),装箱操作将把值类型复制到堆中,并返回对该位置的引用,即使该值已经在堆中(例如,对象的值类型属性),因此您不会得到对原始值变量的引用,但这仍然是一个实现细节,因为值类型应该被视为不可变的。

Um,他知道如何在C#代码中装箱和拆箱。这可能是也可能不是拆箱到堆栈-这是一个实现细节。在某些情况下,即使局部变量也可能在堆上……原始值类型的值也存储在堆上的新对象中?@Lojolnik:堆是一个实现细节,但是的-它在一个新对象(框)中。@SWeko:装箱生成副本的事实并不是一个实现细节。heap是一个实现细节,但是box与原始变量的独立性不是。例如,我的答案中的代码保证打印10而不是11。@JonSkeet:我认为不变性是概念,副本是实现细节。如果装箱未被复制,代码仍将打印10,并且i=11只为i获取一个新的11,而不改变原始值。@SWeko:但是如果它没有复制-如果引用实际上引用了变量-那么更改变量的值将更改取消引用时显示的值,不是吗?你想让我找到保证复制的C#规范吗?请注意,仅仅因为值类型通常应该是不可变的,并不意味着它们是。。。但无论如何副本是有保证的。@SWeko:C#4规范第4.3.1节:“装箱转换意味着制作装箱值的副本。”(规范中甚至有斜体)。@JonSkeet:如果int是不可变的,就不可能更改值,因此引用原始值也不会有问题。复制使它看起来不可变,这在我的书中很好。语言规范确实定义了将进行复制(第4.3.1节),但我想说的是,如果我们将值类型视为不可变的,是否存在复制并不重要。