Как я могу защитить себя от обновления другого объекта поверх текущего объекта по ошибке? - PullRequest
4 голосов
/ 06 апреля 2011

Можете ли вы предложить мне способ, который бы помешал мне в таком случае, когда я работаю со ссылочными типами?

var someCost = new Cost( Price: new Price(1000, "USD")
                        , CostType: "Type-A") ;

var candyCost = new Cost();

// Initialize candyCost.Price
candyCost.Price = someCost.Price; //Now candyCost Price is referencing 
                                 // price of someCost; 

// (.......)
// Some logic and code here
//and I forgot that I was referencing to someCost object's price object
//and I do stupid mistake:

candyCost.Price.Value = 5000; //Now I believe I have updated candyCost price 
                              //but I have also updated someCost!!

Остальная часть истории посвящена отладке, чтобы узнать, почему обновляется цена SomeCost.

Я хотел упростить проблему с этим примером.Надеюсь, если вы меня поняли.

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

Ответы [ 9 ]

8 голосов
/ 06 апреля 2011

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

2 голосов
/ 06 апреля 2011

Зависит от того, что вы хотите достичь с помощью этой строки:

 candyCost.Price = someCost.Price;

Вы хотите сказать, что candyCost и someCost имеют одинаковую цену в данный момент или что они всегда имеют одинаковую цену?

Если вы просто хотите инициализировать candyCost.Price значением, равным , равным someCost.Prize, вам следует клонировать экземпляр Price:

 candyCost.Price = new Price(someCost.Price); // copy constructor pattern inside

(конечно, вы должны реализовать конструктор)

1 голос
/ 06 апреля 2011

Создайте глубокую копию класса Price, реализовав интерфейс IClonnable.Затем, когда вы назначите цену, вы скажете

a.Price = b.Price.Clone(); // will return a new object of the price after assigning the internal value types 

или

  Class Cost{
  private Price _price;

        public Price PriceValue
        {
            get { _price.Clone(); }
            set { _price = value; }
        }
       }

таким образом, вы никогда не забудете

, следовательно, вы не можете получить доступ к полю _price напрямую, если только вы невызовите свойство Getter, которое в конечном итоге вернет глубокую копию Price

1 голос
/ 06 апреля 2011

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

0 голосов
/ 06 апреля 2011

В зависимости от языка вы можете выполнять перегрузку операторов.Итак, перегрузите оператор присваивания (=) и выполните глубокое клонирование в перегруженном теле оператора.

0 голосов
/ 06 апреля 2011

Сделать Cost.Price только для чтения, используя {get;закрытый набор;} Добавить новый метод к Cost с именем SetPrice, который берет Price и создает новый экземпляр Price

SetPrice(Price price)
{
    this.Price = price.Clone();
}

. Вам нужно будет заставить Price реализовать IClonnable

0 голосов
/ 06 апреля 2011

Есть несколько способов сделать это.

  1. Использовать неизменяемые типы - например, String в Java и все примитивные оболочки
  2. Использовать конструкторы копирования для копирования объектов вместоссылка на них

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

Использование конструкторов копирования означает, что вы имеетечтобы убедиться, что всякий раз, когда вы возвращаете объект (например, из получателя), вы фактически создаете новый объект, аналогично всякий раз, когда вы используете переданный объект (например, установщик), вам необходимо его скопировать.

0 голосов
/ 06 апреля 2011

Требуется поведение по значению для свойства Price. Получатель должен вернуть копию объекта Price.

0 голосов
/ 06 апреля 2011

В этом случае я бы предложил использовать struct (тип значения) вместо class (ссылочный тип).Таким образом, невозможно ссылаться на один и тот же экземпляр, потому что нет «ссылки», само значение сохраняется :)

Вы также можете иметь свойства типа Price только для чтения и установитьтолько конструктором.Таким образом, вы можете ссылаться на другую копию, но это не проблема - они оба останутся с одним и тем же значением, потому что для установки нового значения вам потребуется создать новый объект.

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