Как мне скопировать экземпляр объекта? - PullRequest
14 голосов
/ 21 января 2010

Я пытаюсь написать некоторый код, который заполняет List (на самом деле это серия Lists, но мы можем притвориться, что это всего лишь один List). Идея состоит в том, чтобы добавить IPackage к List для общего количества IPackage в заказе. Смотрите следующий код:

        ParseExcel pe = new ParseExcel();
        Pinnacle p = pe.ParsePinnacleExcel();
        Rack r = new Rack(20,2,4.5,96,42,6,25*12);
        foreach (PinnacleStock ps in p.StockList.Where(x => 
                 x.ColorCode == "10" && 
                 x.PackageLength == 30.64))
        {
            for (int i = 1; i <= ps.OnOrder; i++)
            {
                r.TryAddPackage((IPackage)ps);
            }
        }

Кажется, все работает хорошо, поскольку IPackage постоянно добавляется в список. Однако создается впечатление, что добавляется один и тот же экземпляр объекта, то есть объект не копируется при каждом добавлении в список.

Что мне нужно сделать, чтобы копия объекта была вставлена ​​в список, а не просто как дополнительная ссылка

Ответы [ 4 ]

13 голосов
/ 21 января 2010

Затем вам нужно реализовать ICloneable и заменить

r.TryAddPackage((IPackage)ps);

на

r.TryAddPackage((IPackage)ps.Clone());

Вам решать, как Clone должен заполнить новый экземпляр PinnacleStock, который он возвращает.

На самом базовом уровне вы можете сказать

public PinnacleStock : ICloneable {
    public PinnacleStock Clone() {
        return (PinnacleStock)this.MemberwiseClone();
    }
    object ICloneable.Clone() {
        return Clone();
    }
    // details
}

Это будет просто поверхностная копия PinnacleStock.Только вы знаете, правильная ли это семантика для вашего домена.

5 голосов
/ 21 января 2010

Если вам нужна только поверхностная копия, вы можете написать метод быстрого исправления клона:

public class PinnacleStock : ICloneable
{
    public PinnacleStock Clone()
    {
        return (PinnacleStock)this.MemberwiseClone();
    }

    object ICloneable.Clone()
    {
        return Clone();
    }

    // Other methods
}

Если вам нужна глубокая копия (т. Е. Если у PinnacleStock есть подобъекты, которые вы также хотите скопировать), то вам придется написать один самостоятельно.

3 голосов
/ 21 января 2010

Как уже говорили другие, вам нужно сделать эту копию, каким-то специфическим для PinnacleStock способом:

foreach (PinnacleStock ps in p.StockList.Where(x => x.ColorCode == "10" && 
                                                    x.PackageLength == 30.64))
{
  for (int i = 1; i <= ps.OnOrder; i++)
  {
    PinnacleStock clone = ps.CopySomehow();  // your problem
    r.TryAddPackage((IPackage)clone);
  }
}

Однако вы можете спросить, является ли это правильным решением. Вам действительно нужен отдельный экземпляр PinnacleStock? Действительно ли добавление PinnacleStock в стойку создает новый, независимый экземпляр? Планируете ли вы изменять или отслеживать каждую из этих отдельных копий отдельно? Правильно ли, что теперь у вас будут экземпляры PinnacleStock, которых нет в вашем StockList? Не зная вашего домена или семантики PinnacleStock, трудно быть уверенным, но вы можете рассмотреть, скажем, создание объекта PinnacleStockRackEntry для представления экземпляра PinnacleStock - конечно, зависит от предполагаемой семантики!

2 голосов
/ 21 января 2010

Вы должны предоставить логику для копирования объекта самостоятельно. .Net нигде не имеет встроенного глубокого копирования (с заметным потенциальным исключением сериализации). Наиболее близким является метод MemberwiseClone (), но даже он будет копировать ссылки для любых элементов вашего типа, которые сами являются ссылочным типом.

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