2012-03-06 7 views
1

Я новичок в C#. Я из мира Java. Так что я путаюсь со следующим кодом:Получить свойство по ссылке

class A 
    { 
     private PointF point; 

     public A(PointF point) 
     { 
      this.point = point; 
     } 

     public PointF Position 
     { 
      get { return point; } 
     } 
    } 

Я хочу изменить X-координата позиции собственности, поэтому я выполняю:

 A a = new A(new PointF(1,2)); 
     PointF p = a.Position; 
     p.X = 100; 
     Console.WriteLine(a.Position.X); // <--- I have 1 here! 

Интересно, почему выход НЕ ? Как я понял, я получил ссылку на личное поле с свойством Position. Я прав?

Могу ли я изменить свойство без добавления установку свойства и распространение позиции с новым PointF объекта?

+2

Нет, вы не можете. Поскольку PointF является структурой и является типом значений. – Disposer

+0

Да, вы можете. Можете ли вы вставить код своего PointF, я думаю, что установщик на PointF.X не делает то, что он должен делать. - EDIT: oh Я не понимал, что PointF был структурой, а не классом ... Итак, ваша переменная 'p' - это новая структура, скопированная из a.Position. Если вы хотите, чтобы это была ссылка, вам нужно либо инкапсулировать PointF в класс, либо определить новый тип как класс. Или вы можете использовать класс Point. –

+0

Вы уверены, что ?? !!! Я тестировал, и он работает. Не могли бы вы также добавить класс PointF в свой образец. EDIT: lol я не видел структуру ни – Guillaume

ответ

6

Нет; PointF - struct, поэтому он имеет семантику копирования и не является объектом; как только вы его получите, это отдельная и изолированная копия (если вы не используете что-то вроде ref/out, что ... более тонкое). Строка фактически копируется несколько раз в вашем примере.

Кстати, следствием этого является то, что это на самом деле очень плохая идея, чтобы иметь изменяемые структур - поэтому в большинстве случаев следует избегать сценарий, в котором вы можете сказать:

p.X = 100; 

так, что вызывает больше путаницы, чем помогает. В частности, следующее совершенно недопустимо:

a.Position.X = 100; // won't even compile 

(здесь компилируемая пятнистость, что вы меняете копию структуры, которая существует только в самой мутации, что означает, что ваше изменение идет нигде, и почти конечно, ошибка)

0

вам нужно использовать сохраненные слова из (функции) и реф (если отправить функции) для передачи параметров по ссылке

+0

Передача структурной ссылки не позволяет вам * хранить * ссылку; он будет разыменован при назначении на что-либо. –

2

PointF - это структура. Структуры .Net Framework: valueTypes. Таким образом, ваш пример всегда будет распечатан 1.

Не имеет значения, что вы используете его в классе. Каждый раз, когда вы назначаете значение переменной типа значения, будет скопировано значение.

+1

Вы имеете в виду, что он всегда будет распечатывать 1, а не 100. –

+0

thx для подсказки, отредактировал мой ответ –

2

PointF - тип значения со всеми последствиями. Если вы хотите изменить только свойство «X» значения PointF в свойстве, вам нужно скопировать значение в переменную, изменить свойство «X» и установить измененное значение свойства.

var cls = new A(); 
var point = cls.Point; 
point.X = 15; 
cls.Point = point; 
0

Интересно, почему вы компилятор не дает вам предупреждения. Что здесь происходит, так это то, что вы не возвращаете ссылку на PointF, которая, по-видимому, является типом значений, на самом деле вы возвращаете копию. Затем вы изменяете это свойство X. Конечно, эта работа не работает.

+0

Это не ошибка (хотя это нецелесообразно), потому что вы все еще можете сделать что-то интересное с измененной локальной копией. Время, когда возникают ошибки, когда вы пытаетесь это прямо на property-get. –

+0

@MarcGravell Ах, конечно, вы правы. – dowhilefor

0

В вашем примере p и a представляют собой два разных объекта, поэтому изменение первого не влияет на последнее.

+1

p не является объектом * вообще * –

0

В C#, вы имеете properties

class A 
{ 
    public PointF Position {get;set;} 

    public A(PointF point) 
    { 
     this.Position = point; 
    } 
} 

A a = new A(new PointF(1,2));  
    a.Position.X = 100 
    Console.WriteLine(a.Position.X); 
+0

Это даже не компилируется, так как 'PointF' является' struct'; вы не можете мутировать 'struct' через' get' –

2

В C# существуют два типа переменных - типов значений и ссылочных типов. При присвоении типов значений они копируются - для ссылочных типов копируется ссылка.

Point - тип значения (a struct) и по назначению получает скопированный. Итак:

PointF p = a.Position; 

p является копия из a.Position, совершенно отдельно от него. Итак:

p.X = 100; 

Изменяет значение X на p, оставляя a.Position.X нетронутыми.

Смежные вопросы