好奇:将C#struct转换为对象仍然会复制它

好奇:将C#struct转换为对象仍然会复制它,c#,c#-4.0,clr,boxing,C#,C# 4.0,Clr,Boxing,这个问题与其说是一个真正的问题,不如说是出于好奇。考虑下面的代码(C<4,如果重要的话): 这将产生以下结果: Point Struct Before: 3;5 Point Object Before: 3;5 Point Struct After: 10;5 Point Object After: 3;5 现在,它可以正常工作,这意味着GetPoint()返回的点被复制而不是引用。(否则最后一行也应该是“10;5”。) 我现在的问题是:为什么这样做?编译器如何知道是复制还是引用对象?这是否意

这个问题与其说是一个真正的问题,不如说是出于好奇。考虑下面的代码(C<4,如果重要的话):

这将产生以下结果:

Point Struct Before: 3;5
Point Object Before: 3;5
Point Struct After: 10;5
Point Object After: 3;5
现在,它可以正常工作,这意味着
GetPoint()
返回的点被复制而不是引用。(否则最后一行也应该是“10;5”。)

我现在的问题是:为什么这样做?编译器如何知道是复制还是引用对象?这是否意味着此决策是在运行时而不是在编译期间完成的


此外,这现在允许我将
点设置为
null
,而
struct
s不能设置为
null
。结构是否自动转换为可空类型?

您正在观察调用的进程。它本质上是将值类型转换为引用类型。

您正在观察调用的过程。它本质上是将值类型转换为引用类型。

您不是将
myPoint
转换为对象,而是创建
myPoint
结构的副本(通过
GetPoint
方法)并为其分配对象引用。

您不是将
myPoint
转换为对象,您只需创建
myPoint
结构的副本(通过
GetPoint
方法)并为其分配对象引用

此外,这现在允许我将point设置为null,而structs不能设置为null。结构是否自动转换为可为null的类型

你误解了整个过程:

int i = 5;
object o = i; //Creates a new Int32 with value 5 and assigns it to the object'o' reference storing the value on the garbage collected heap. This is what is called boxing.
object o = null //Simply assigns 'null' to the object reference, it does nothing to the boxed value type 'o' was referencing before.
在上面的示例中,装箱的
int
最终将由GC从垃圾收集堆中收集,因为不再有活动引用指向它

此外,这现在允许我将point设置为null,而structs不能设置为null。结构是否自动转换为可为null的类型

你误解了整个过程:

int i = 5;
object o = i; //Creates a new Int32 with value 5 and assigns it to the object'o' reference storing the value on the garbage collected heap. This is what is called boxing.
object o = null //Simply assigns 'null' to the object reference, it does nothing to the boxed value type 'o' was referencing before.

在上面的示例中,装箱的
int
最终将由GC从垃圾收集堆中收集,因为不再有活动引用指向它。

虽然Microsoft在某种意义上声称所有类型都源自对象,但将值类型视为完全不在类型系统中的东西更有用,但是它们在类型系统中具有装箱等价物(所有这些等价物都派生自ValueType),以及它们与装箱等价物之间的加宽转换运算符。如果将结构传递给需要对象的例程,那么实际上并不是传递值类型,而是传递值类型的装箱等价物。如果这被传递给其他期望对象的例程,它们将继续使用相同的装箱对象。如果它被传递给需要该结构的例程,它将被转换回一个与这些例程一起使用的结构。请注意,每次转换时,都会对该值进行快照;对快照的更改不会影响复制的实体,反之亦然。

虽然Microsoft在某种意义上声称所有类型都派生自object,但将值类型视为完全在类型系统之外,但在类型系统中具有装箱等价物(所有类型都派生自ValueType)的对象更为有用,以及它们与装箱等价物之间的加宽转换运算符。如果将结构传递给需要对象的例程,那么实际上并不是传递值类型,而是传递值类型的装箱等价物。如果这被传递给其他期望对象的例程,它们将继续使用相同的装箱对象。如果它被传递给需要该结构的例程,它将被转换回一个与这些例程一起使用的结构。请注意,每次转换时,都会对该值进行快照;对快照的更改不会影响复制的实体,反之亦然。

点是值类型,而不是引用类型。这就是为什么。我知道
Point
是一种值类型。这就是我整个问题的重点。
point
是一种值类型,而不是引用类型。这就是为什么。我知道
Point
是一种值类型。这就是我整个问题的重点。Int32(以及任何其他装箱类型)的问题是它们也都是值类型。所以您仍然会将值类型分配给引用类型。@Sebastian我知道这已经晚了,但是
ValueType
仍然继承自
object
,因此将值类型分配给
object
是完全合法的。这是另一个问题,Int32(以及任何其他装箱类型)的问题是它们也都是值类型。所以您仍然会将值类型分配给引用类型。@Sebastian我知道这已经晚了,但是
ValueType
仍然继承自
object
,因此将值类型分配给
object
是完全合法的。相反,这是个问题。啊-好的。我只从Java知道装箱,但是装箱类型(例如
int
Integer
)是引用类型,而在C#中是值类型。啊-好的。我只从Java知道装箱,但是装箱类型(例如
int
Integer
)是引用类型,而在C#中是值类型。