C# 是否可以在不丢失原始引用的情况下删除列表中的项目?
好的,这有点难问,但我会试试。 我有一个包含对象(批次)的列表,其中再次包含一个包含对象(晶圆)的列表。 当我改变晶圆中的一个值时,它在两个列表中都会改变!这就是我想要的。 但当我想从复制列表中删除晶圆时,它不应该从原始列表中删除。所以我想在每个批次中都有一个新的晶片列表,但对晶片的引用应该与原始批次中的相同,因为我想更改晶片的值,它应该更改原始晶片和复制晶片中的值。如果没有深度复制,这可能吗 为了更好地解释,我有以下代码:C# 是否可以在不丢失原始引用的情况下删除列表中的项目?,c#,.net,C#,.net,好的,这有点难问,但我会试试。 我有一个包含对象(批次)的列表,其中再次包含一个包含对象(晶圆)的列表。 当我改变晶圆中的一个值时,它在两个列表中都会改变!这就是我想要的。 但当我想从复制列表中删除晶圆时,它不应该从原始列表中删除。所以我想在每个批次中都有一个新的晶片列表,但对晶片的引用应该与原始批次中的相同,因为我想更改晶片的值,它应该更改原始晶片和复制晶片中的值。如果没有深度复制,这可能吗 为了更好地解释,我有以下代码: public class Lot {
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;
}
公共类地块
{
公共字符串LotName{get;set;}
公共列表晶圆{get;set;}
}
公共级晶圆
{
公共字符串WaferName{get;set;}
}
[测试]
public void ListInListTest()
{
//一些测试数据
List lotList=新列表();
批次=新批次();
lot.LotName=“Lot1”;
lot.Wafers=新列表();
晶圆=新晶圆();
wafer.WaferName=“Wafer1”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer2”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer3”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer4”;
批次。晶圆。添加(晶圆);
lotList.Add(批次);
批次=新批次();
lot.LotName=“Lot1”;
lot.Wafers=新列表();
晶圆=新晶圆();
wafer.WaferName=“Wafer1”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer2”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer3”;
批次。晶圆。添加(晶圆);
晶圆=新晶圆();
wafer.WaferName=“Wafer4”;
批次。晶圆。添加(晶圆);
lotList.Add(批次);
//复制列表
List copyList=复制列表(lotList);
//这很有效。它只会删除复制列表中的部分,而不会删除复制列表中的部分
//原版
复制列表。删除(1);
//这与我想要的不一样。它会从复制列表中删除晶圆
//还有原来的名单。我只是想,名单会改变
//在复制的列表中
复制列表[0]。晶圆。移除(0);
}
私有列表CopyList(列表lotList)
{
列表结果=新列表(lotList);
foreach(结果中的批次)
{
lot.Wafers=新列表(lot.Wafers);
}
返回结果;
}
我希望它不是那么混乱?我希望我的问题得到足够好的解释。问题是,通过维护对主列表的引用来创建克隆列表。您应该使用以下内容:
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;
}
private List copyrist(列表)
{
列表克隆=新列表();
foreach(清单中的l标段)
{
列表晶圆=新列表();
foreach(在l晶片中为w晶片)
晶片。添加(w);
添加(新批(){LotName=l.LotName,Wafers=Wafers});
}
返回克隆;
}
简短回答:是的,这是可能的。但是,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;
}
私有列表复制列表(列表lotList)
{
列表结果=新列表();
for(int i=0;i
这将创建一个新的lotlist,并将所有现有的晶圆添加到其中。据我所知,没有现成的方法可以让您随心所欲。以下是原因的简要说明:
列表
(最左侧)包含对批次
对象的引用,而该对象又包含对其两个成员变量的引用
如果您希望对LotName
和Wafers
列表的成分进行更改,如您所述,最简单的解决方案是在列表之间共享对Lot
对象的引用:
现在,您可以了解为什么不可能使用此解决方案单独修改晶圆列表中的项目了-您无法摆脱使用相同对象引用的事实
通过分享推荐信,你失去了控制行为差异的能力。为了实现您想要的,我认为您必须对批次
实例进行深度复制,然后您可以通过某种模式管理更改的传播。我想我可以看到您的问题所在。在您的复制列表中
可以有效地克隆列表,即
lot.Wafers = new List<Wafer>(lot.Wafers);
这很好,因为您正在操作Lot
列表的副本。然而,当你打电话时
copyList.RemoveAt(1);
copyList[0].Wafers.RemoveAt(0);
您正在修改两个列表仍在引用的批次
实例。要解决此问题,您需要克隆批次
对象本身以有效地更改引用,即
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)
});
}
List结果=新列表(lotList.Count);
foreach(批次列表中的批次项目)
{
结果。添加(新批次()
{
LotName=item.LotName,
晶圆=新列表(项目.晶圆)
});
}
因此,您将丢失批次
对象本身在两个列表中的自动更新,但您仍将保留它以修改单个晶圆
对象(因为它们的参考不会更改)
总之,你要问的是:
如何在具有不同属性引用的同时保留相同的对象引用
这个问题的答案是-你不能。你应该为列表使用两个单独的变量,例如ListLotA
和ListLotB
。如果您希望能够删除
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);
ListLotB.Wafers[1].WaferName = "New Value";
ListLotA.Wafers.Remove(w2);