2015-10-06 3 views
1

Мне было интересно, можно ли это сделать, не используя сеттеры.Изменение структурных полей после распаковки объекта

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

(Un) бокс является копией операции. Вы не изменяете ценность своей коробчатой ​​структуры, вы просто изменяете копию, которую вы выбрасываете сразу после.

Это не имеет никакого отношения к сеттерам. Вы просто изменяя неверное значение :)

Если вам нужно изменить коробочную-структуру, необходимо скопировать его в основном вручную, а затем скопировать его обратно:

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); 
     } 
    } 
} 
Смежные вопросы