Всегда ли свойства неизменны? - PullRequest
0 голосов
/ 16 января 2019

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

Я обновляю старый код C #, и VS2017 советует мне несколько советов по рефакторингу, например, частные члены с автоматически предоставленными свойствами для автоматически сгенерированных свойств.

VS делает это легко с парой кликов, и все компилируется просто отлично. Проблема в том, что код не работает, как раньше.

Рассмотрим следующий пример сокращенного кода:

using System;

public class Program    
{
    struct A
    {
        public A(int x) : this()
        {
            X = x;
        }

        public int X { get; private set; }

        public void Update(int y)
        {
            X += y;
        }
    }

    class B
    {
        private A _secondVar;

        public B()
        {
        }

        public A MyVar { get; set; }

        public A SecondVar
        {
            get { return _secondVar; }
            protected set { _secondVar = value; }
        }           

        public void Foo(int z)
        {
            MyVar.Update(z);
            _secondVar.Update(z);
        }       
    }


    public static void Main()
    {
        B b = new B();
        Console.WriteLine("BEFORE: b.MyVar: " + b.MyVar.X + ", b.SecondVar: " + b.SecondVar.X );
        b.Foo(23);
        Console.WriteLine("AFTER: b.MyVar: " + b.MyVar.X + ", b.SecondVar: " + b.SecondVar.X );
    }
}

Вывод:

BEFORE: b.MyVar: 0, b.SecondVar: 0
AFTER: b.MyVar: 0, b.SecondVar: 23

Я ожидаю, что вызов MyVar.Update(z) обновит свойство, а последующие вызовы MyVar.X должны предоставить обновленное значение.

Это ожидаемое поведение или ошибка в C #?

1 Ответ

0 голосов
/ 16 января 2019

Вы используете изменяемые структуры, что категорически не рекомендуется именно по этой причине.

Ваш код здесь:

public void Foo(int z)
{
    MyVar.Update(z);
    _secondVar.Update(z);
}

эквивалентен этому:

public void Foo(int z)
{
    A tmp = MyVar; // Creates a copy
    tmp.Update(z);
    _secondVar.Update(z);
}

Ваш код _secondVar.Update(z) меняет значение _secondVar, потому что вы вызываете его непосредственно для переменной.Это не относится к вашему свойству - использование метода получения свойства фактически вызывает метод, который возвращает значение, которое является копией значения переменной.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...