我正在尝试编写一些填充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
重复添加到列表中的情况下,一切似乎都运行良好。但是,似乎正在添加对象的相同实例,即每次将对象添加到列表时都不会复制该对象。
我需要做些什么才能确保将对象的 副本 插入到列表中,而不仅仅是另外一个参考?
答案 0 :(得分:13)
然后你需要实现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
的浅表副本。只有您知道这是否是您域名的正确语义。
答案 1 :(得分:5)
如果您只需要浅拷贝,那么您可以编写快速修复克隆方法:
public class PinnacleStock : ICloneable
{
public PinnacleStock Clone()
{
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone()
{
return Clone();
}
// Other methods
}
如果您需要深层复制(例如,如果PinnacleStock
包含您想要复制的子对象),那么您需要自己编写一个。
答案 2 :(得分: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的实例 - 当然取决于预期的语义!
答案 3 :(得分:2)
您必须提供自己复制对象的逻辑。 .Net没有内置的深拷贝(序列化有明显的潜在例外)。最接近的是MemberwiseClone()方法,但即使这样也会复制您自己类型的任何成员的引用,这些成员本身就是引用类型。