Как скопировать экземпляр объекта?
Я пытаюсь написать код, который заполняет 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
неоднократно добавляется в список. Однако кажется, что тот же экземпляр объекта добавляется, т.е. Объект не копируется каждый раз, когда он добавляется в список.
Что мне нужно сделать, чтобы убедиться, что в список вставляется копия объекта, а не только дополнительная ссылка?
Ответы
Ответ 1
Затем вам нужно реализовать 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
. Только вы знаете, является ли это правильной семантикой для вашего домена.
Ответ 2
Если вам нужна только мелкая копия, вы можете написать метод быстрого клонирования:
public class PinnacleStock : ICloneable
{
public PinnacleStock Clone()
{
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone()
{
return Clone();
}
// Other methods
}
Если вам нужна глубокая копия (т.е. если PinnacleStock
есть под-объекты, которые вы хотите скопировать), тогда вам нужно будет написать их самостоятельно.
Ответ 3
Как говорили другие, вам нужно будет сделать эту копию в определенном способе 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 - конечно, зависит от предполагаемой семантики!
Ответ 4
Вы должны предоставить логику для копирования объекта самостоятельно..Net не имеет встроенного в глубокую копию встроенного (с заметным потенциальным исключением сериализации). Ближе всего это метод MemberwiseClone(), но даже это будет копировать ссылки для любых членов вашего типа, которые сами являются ссылочным типом.