tags:

views:

178

answers:

4
+7  A: 

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.

Jason
This worked great. As a nod to other suggestions, for a Shallow Clone, you can use `MemberwiseClone()`. However, since it's protected, you have to implement it within the actual class of the object to Clone. Here's how I did it: `public Object Clone(){ return (PinnacleStock)this.MemberwiseClone();}`
Ben McCormack
@Ben McCormack: Right. And you can go one step further and declare a method `Clone` that does return a `PinnacleStock` and have `ICloneable.Clone` implemented explicitly. See my edit.
Jason
+2  A: 

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.

Joel Coehoorn
+2  A: 

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.

Aaronaught
To note, `MemberwiseClone` is a `protected` method. It is not publicly accessible. Therefore the above will not compile unless you hide the base method `MemberwiseClone` and declare a `public` method `MemberwiseClone`.
Jason
@Jason I noticed that it didn't compile. However, what do you mean by "hide the base method...and declare a public method"?
Ben McCormack
I think I found an answer: http://stackoverflow.com/questions/2023210/help-with-c-memberwiseclone
Ben McCormack
@Ben McCormack: Well, you really shouldn't do this, but you could say `public new PinnacleStock MemberwiseClone() { return (PinnacleStock)base.MemberwiseClone(); }`. If you think that `MemberwiseClone` will solve the problem that you need to solve then it is much better to say `public PinnacleStock Clone() { return (PinnacleStock)this.MemberwiseClone(); } object ICloneable.Clone() { return Clone(); }` I'll spell this out in my original answer.
Jason
@Jason: You're right, I don't know how I managed to miss that. I rewrote it using a public method on the class.
Aaronaught
@Aaronaught: Ah, it's easy to miss. But one more correction; the return type of `ICloneable.Clone` is `object` so the above is not an implementation of `Clone`. The best way is to add an explicit interface implementation of `ICloneable.Clone` and then you're good to go.
Jason
Incidentally, I've always hated the `ICloneable` interface. It doesn't *do* anything, and it's not generic. For some reason it just annoys me implementing a core interface when the framework itself never looks at it. I added it here because I was writing a `Clone` method anyway...
Aaronaught
@Jason: Ha ha, and that's another reason I hate it. ;)
Aaronaught
@Aaronaught: Oh I completely agree. I hate that it could be a shallow copy, it could be a deep copy, or it could be something in between. I also hate that it's not strongly typed.
Jason
+3  A: 

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!

itowlson