Получить недвижимость по ссылке - PullRequest
1 голос
/ 06 марта 2012

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

    class A
    {
        private PointF point;

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

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

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

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

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

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

Ответы [ 8 ]

6 голосов
/ 06 марта 2012

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

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

p.X = 100;

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

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

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

2 голосов
/ 06 марта 2012

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

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

PointF p = a.Position;

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

p.X = 100;

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

2 голосов
/ 06 марта 2012

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

var cls = new A();
var point = cls.Point;
point.X = 15;
cls.Point = point;
2 голосов
/ 06 марта 2012

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

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

0 голосов
/ 06 марта 2012

В C # у вас есть свойства

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 голосов
/ 06 марта 2012

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

0 голосов
/ 06 марта 2012

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

0 голосов
/ 06 марта 2012

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

...