2015-10-06 21 views
1

我想知道是否有可能做到这一点,而不使用setter。拆箱后更改结构字段到对象

void Main() 
{ 
    Point p = new Point(); 
    p.x = 7; 
    Object o = p; 
    ((Point)o).y = 9; // This doesnt work ! 
    ((Point)o).Print(); 

} 

struct Point 
{ 
    public int x, y; 
    public void Print() 
    { 
     System.Console.WriteLine("x= "+this.x+"\ny= "+this.y); 
    } 
} 

是否可以通过转换和取消装箱来更改y值? 在此先感谢

回答

2

(联合国)拳击是复制操作。你并没有修改你的盒装结构的价值,你只是修改一个副本 - 你马上扔掉。

这与setters无关。你只是修改了错误的价值:)

如果您需要修改装箱的结构,需要基本手动复制它,然后再拷贝回去:

var p2 = (Point)o; 
p2.y = 9; 
o = (object)p2; 

不用说,这有点浪费。如果你真的需要做这样的事情(而且很难看到为什么),您可能希望创建一个手动拳击对象,而不是 - 像

class MyBox<T> where T : struct 
{ 
    public T Value; 
} 

,它允许你做

var o = (object)new MyBox<Point> { Value = p }; 
((MyBox<Point>)o).Value.y = 9; 

请注意,Value是一个字段不是一个属性 - 而不是复制,我们直接引用“盒装”值。

+0

好了,我知道+ - 它做什么,它通过田间地头到堆栈的顶部,然后到堆,然后与邻必须的那部分参考堆(仍然学习不讨厌xD)但我不能做oy = 9;那么我可以在拳击后改变这个值吗? – Franmcod

+0

@NoobCoder不,盒装值实​​际上是不可变的。您需要填入新的值,并用新的值替换旧的参考值。 'MyBox'对于这种场景更有用,因为它避免了自动装箱 - 而且*不会创建副本(除非有一些自定义的铸造操作符,当然:))。 – Luaan

0

如果你可以改变struct Point,你可以做的就是让Point实现一个接口,然后将盒装结构转换为接口。这是有效的,因为当您将装箱点投射到界面时不会发生拆箱。

这里的示例代码,

public static void Main() 
    { 
     Point p = new Point(); 
     p.x = 7; 
     object o = p; 
     ((IModifiablePoint)o).Y = 9; // This works 
     ((Point)o).Print(); 

    } 

    interface IModifiablePoint 
    { 
     int X { get; set; } 
     int Y { get; set; } 
    } 

    struct Point : IModifiablePoint 
    { 
     public int x, y; 

     public int X 
     { 
      get { return x; } 

      set { x = value; } 
     } 

     public int Y 
     { 
      get { return y; } 

      set { y = value; } 
     } 

     public void Print() 
     { 
      System.Console.WriteLine("x= " + this.x + "\ny= " + this.y); 
     } 
    } 
}