I'm trying to write some code that populates a List
(actually, it's a series of Lists
, but we can pretend it's just one List
). The idea is to add an IPackage
to the List
for the total quantity of IPackage
on order. See the following code:
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);
}
}
Everything seems to be working well, insofar as the IPackage
is repeatedly added to the list. However, it seems that the same instance of the object is being added, i.e. the object is not being copied each time it's added to the list.
What do I need to do to ensure that a copy of the object is inserted into the list, and not just an additional reference?
Then you need to implement ICloneable
and replace
r.TryAddPackage((IPackage)ps);
with
r.TryAddPackage((IPackage)ps.Clone());
It's up to you to decide how Clone
should populate the new instance of PinnacleStock
that it returns.
At the most basic level, you could say
public PinnacleStock : ICloneable {
public PinnacleStock Clone() {
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone() {
return Clone();
}
// details
}
This will just do a shallow copy of PinnacleStock
. Only you know if this is the correct semantics for your domain.
If you only need a shallow copy, then you can write a quick-fix clone method:
public class PinnacleStock : ICloneable
{
public PinnacleStock Clone()
{
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone()
{
return Clone();
}
// Other methods
}
If you need a deep copy (i.e. if PinnacleStock
has sub-objects that you want to be copied as well), then you will need to write one yourself.
As others have said, you would need to make that copy, in some PinnacleStock-specific way:
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);
}
}
However, you might want to question whether this is the right solution. Do you really need a separate instance of the PinnacleStock? Does adding a PinnacleStock to a Rack really create a new, independent instance? Are you planning to modify or track each of these individual copies separately? Is it correct that now you will have PinnacleStock instances that don't appear in your StockList? Not knowing your domain or the semantics of PinnacleStock, it's hard to be sure, but you might want to consider, say, creating a PinnacleStockRackEntry object to represent an instance of a PinnacleStock -- depends on the intended semantics of course!
You have to supply the logic to copy the object yourself. .Net does not have deep-copy built-in anywhere (with the notable potential exception of serialization). The closest it comes is the MemberwiseClone() method, but even that would copy references for any members of your type that are themselves reference type.