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

col*_*ang 5 c# il boxing unboxing

struct Point
{
    public int x;
    public int y;
}
void Main()
{
    Point p;
    p.x = 1;
    p.y = 1;
    Object o = p;
    ((Point) o).x = 4; // error
    ((Point) o).x = 5; // error
    ((Point) o).x = 6; // error
    p = (Point) o  // expect 6
}
Run Code Online (Sandbox Code Playgroud)

为什么不编译

ldloc.1 // o
unbox Point
ldc.i4.4
stfld Point.x
Run Code Online (Sandbox Code Playgroud)

C++ CLI允许的地方.

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

cHa*_*Hao 10

由于值类型的工作方式,boxed Point是原始文件的副本,并通过强制转换来"拆箱" Point创建另一个副本.从C#语言规范(§1.3,"类型和变量"):

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

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

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

  • 但是代码试图查看副本的值,而不是原始的值.为什么你不能修改它? (2认同)
  • 拳击本身创建一个副本.(ECMA-335,§1.8.2.4:"装箱任何值类型的值都会产生其盒装值;即包含原始值的按位副本的相应盒装类型的值.") (2认同)