2015-10-06 53 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); 
     } 
    } 
}