为什么我不能修改取消装箱转换的结果?

struct Point { public int x; public int y; } void Main() { Point p; px = 1; py = 1; Object o = p; ((Point) o).x = 4; // error ((Point) o).x = 5; // error ((Point) o).x = 6; // error p = (Point) o // expect 6 } 

为什么不编译

 ldloc.1 // o unbox Point ldc.i4.4 stfld Point.x 

C ++ CLI允许的地方。

对于那些不知道的人, unbox不需要创建值类型的副本,而是将指针推送到堆栈上的值。 只有分配才能创建副本。

由于值类型的工作原理,装箱的Point是原始的副本,并且通过转换为Point来“拆箱”它会创建另一个副本。 从C#语言规范(§1.3,“类型和变量”):

当值类型的值转换为类型对象时,将分配一个对象实例(也称为“框”)来保存该值,并将该值复制到该框中。 相反,当对象引用转换为值类型时,将检查引用的对象是否为正确值类型的框,如果检查成功,则复制框中的值。

修改副本不会改变原始版本,所以允许它没有多大意义。

至于C ++ ……当然,C#的规则并不一定适用于它。 🙂 CLR实际上对指针和引用的灵活性比你最初想象的要大得多,而C ++ – 以这种灵活性着称 – 可能会利用它。

您无法执行此操作,因为取消装箱的结果是装箱值的副本,而不是装箱值本身。 并且将object转换为值类型是拆箱的定义。 因此,如果编译器允许您这样做,那将非常令人困惑,因为分配实际上不会做任何事情。

认为你的代码在C ++ / CLI中工作的原因是因为该语言通常更多地支持使用引用工作(或不工作),包括强类型框(例如Point^ )和将(某些)类视为值类型(例如使用没有^ MemoryStream