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

Seb*_*ski 1 c# clr boxing c#-4.0

这个问题更多的是出于好奇而不是真正的问题.请考虑以下代码(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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这输出如下:

Point Struct Before: 3;5
Point Object Before: 3;5
Point Struct After: 10;5
Point Object After: 3;5
Run Code Online (Sandbox Code Playgroud)

现在,这应该工作,这意味着返回的点GetPoint()被复制而不是被引用.(否则最后一行也会读"10; 5".)

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

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

InB*_*een 8

此外,现在允许我将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.
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,int最终将由垃圾收集堆从GC收集盒装,因为没有实时引用指向它.


Zru*_*uty 5

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