好的,这有点难以问,但我会尝试。 我有一个带有对象的列表(Lots),它再次包含一个带有对象的列表(Wafers)。 当我更改晶圆内的值时,它将在两个列表中更改!这就是我想要的。 但是当我想从复制的列表中删除晶圆时,不应该从原始列表中删除它。所以我想在每个批次中都有一个新的晶圆列表,但是对晶圆的参考应该与原始晶圆相同,因为我想改变晶圆的值,它应该改变原始晶圆和复制晶圆的值。没有深层复制可能吗?
我有以下代码,以便更好地解释它:
public class Lot
{
public string LotName { get; set; }
public List<Wafer> Wafers { get; set; }
}
public class Wafer
{
public string WaferName { get; set; }
}
[Test]
public void ListInListTest()
{
//Some Testdata
List<Lot> lotList = new List<Lot>();
Lot lot = new Lot();
lot.LotName = "Lot1";
lot.Wafers = new List<Wafer>();
Wafer wafer = new Wafer();
wafer.WaferName = "Wafer1";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer2";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer3";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer4";
lot.Wafers.Add(wafer);
lotList.Add(lot);
lot = new Lot();
lot.LotName = "Lot1";
lot.Wafers = new List<Wafer>();
wafer = new Wafer();
wafer.WaferName = "Wafer1";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer2";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer3";
lot.Wafers.Add(wafer);
wafer = new Wafer();
wafer.WaferName = "Wafer4";
lot.Wafers.Add(wafer);
lotList.Add(lot);
//Copy the List
List<Lot> copyList = CopyList(lotList);
//That works. It removes the lot just in the copyList but not in
//the original one
copyList.RemoveAt(1);
//This works not like i want. It removes the wafers from the copied list
//and the original list. I just want, that the list will be changed
//in the copied list
copyList[0].Wafers.RemoveAt(0);
}
private List<Lot> CopyList(List<Lot> lotList)
{
List<Lot> result = new List<Lot>(lotList);
foreach (Lot lot in result)
{
lot.Wafers = new List<Wafer>(lot.Wafers);
}
return result;
}
我希望不是那么混乱?我希望我的问题解释得很好。
答案 0 :(得分:7)
我想我可以看到你的问题在这里。在你的CopyList
中,你有效地克隆了列表,即
lot.Wafers = new List<Wafer>(lot.Wafers);
但是,这里要注意的关键点是Lot
对象的引用仍然是相同的 - 所以有效地克隆&amp;也替换原始列表中的Wafers
属性。
致电时
copyList.RemoveAt(1);
这很好,因为您正在操纵Lot
列表的副本。但是,当你打电话
copyList[0].Wafers.RemoveAt(0);
您正在修改两个列表仍在引用的Lot
实例。要解决这个问题,您需要克隆Lot
对象本身以有效地更改引用,即
List<Lot> result = new List<Lot>(lotList.Count);
foreach (Lot item in lotList)
{
result.Add(new Lot()
{
LotName = item.LotName,
Wafers = new List<Wafer>(item.Wafers)
});
}
因此,您将失去Lot
对象本身的两个列表中的自动更新,但您仍然会保留它以修改单个Wafer
对象(因为它们的参考不会有改变)。
总而言之,您实际要问的是:
如何在具有不同属性引用的同时保留相同的对象引用?
这个问题的答案是 - 你做不到。
答案 1 :(得分:3)
据我所知,没有开箱即用的方式让你做你想做的事。以下简要说明原因:
List<Lot>
(最左侧)包含对Lot
对象的引用,该对象又包含对其成员变量的引用。
如果您希望在描述时传播LotName
和Wafers
列表的组成部分的更改,最简单的解决方案是在列表之间共享对Lot
对象的引用:
现在您可以看到为什么不可能使用此解决方案独立修改Wafers
列表中的项目 - 您无法摆脱使用相同对象引用的事实!
通过共享引用,您将失去控制行为差异的能力。为了实现您的目标,我认为您必须对Lot
个实例进行深层复制,然后您可以通过某种Observer模式管理更改的传播。
答案 2 :(得分:0)
问题是您通过维护主列表的引用来创建克隆列表。你应该使用类似的东西:
private List<Lot> CopyList(List<Lot> list)
{
List<Lot> clone = new List<Lot>();
foreach(Lot l in list)
{
List<Wafer> wafers = new List<Wafer>();
foreach(Wafer w in l.Wafers)
wafers.Add(w);
clone.Add(new Lot(){ LotName = l.LotName, Wafers = wafers });
}
return clone;
}
答案 3 :(得分:0)
简短回答:是的,这是可能的。但是,CopyList方法应如下所示
private List<Lot> CopyList(List<Lot> lotList)
{
List<Lot> result = new List<Lot>();
for (int i = 0; i < lotList.Count; i++)
{
Lot lot = new Lot();
lot.LotName = lotList[i].LotName;
lot.Wafers = new List<Wafer>(lotList[i].Wafers);
result.Add(lot);
}
return result;
}
这将创建一个新的批次清单并将所有现有的晶圆添加到其中。
答案 4 :(得分:0)
您应该为列表使用两个单独的变量,例如ListLotA
和ListLotB
。如果您希望能够从一个列表中删除Wafer
而不从另一个列表中删除它,同时调整Wafer
以便它反映在两个列表中,您应该从一个列表中复制晶圆列表到另一个,即使用临时数组。
下面的示例代码说明了这一点:
List<Lot> ListLotA = new List<Lot>();
Wafer w1 = new Wafer() { WaferName = "w1" };
Wafer w2 = new Wafer() { WaferName = "w2" };
Wafer w3 = new Wafer() { WaferName = "w3" };
ListLotA.Wafers.Add(w1);
ListLotA.Wafers.Add(w2);
ListLotA.Wafers.Add(w3);
List<Lot> ListLotB = new List<Lot>();
// At this point adding w1, w2, w3 to the second list is possible, but let's
// assume it's not and you have to copy them from the first list.
Wafer[] wArray = new Wafer[ListLotA.Wafers.Count];
ListLotA.Wafers.CopyTo(wArray);
ListLotB.Wafers.AddRange(wArray);
ListLotA
和ListLotB
是单独的对象,例如它们有不同的参考,但各个晶圆的列表具有相同的参考。
ListLotB.Wafers[1].WaferName = "New Value";
以上一行会改变ListLotB中索引1的Wafer,但它也会影响ListLotA中的相同Wafer(尽管它的索引)。
ListLotA.Wafers.Remove(w2);
这会从ListLotA中删除Wafer w2
,但不会从ListLotB中删除。