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

这个问题更多的是出于好奇而不是真正的问题。 请考虑以下代码(C#4.0,如果重要):

class Program { static Point myPoint = new Point(3, 5); static void Main(string[] args) { Console.WriteLine("Point Struct Before: " + myPoint); object point = GetPoint(); Console.WriteLine("Point Object Before: " + point); myPoint.X = 10; Console.WriteLine("Point Struct After: " + myPoint); Console.WriteLine("Point Object After: " + point); } static object GetPoint() { return myPoint; } } 

这输出如下:

 Point Struct Before: 3;5 Point Object Before: 3;5 Point Struct After: 10;5 Point Object After: 3;5 

现在,这可以正常工作,这意味着GetPoint()返回的点被复制而不是被引用。 (否则最后一行也会读“10; 5”。)

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

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

您正在观察名为拳击的过程。 它实质上将值类型转换为引用类型。

此外,现在允许我将point设置为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因为没有实时引用指向它。

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

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