是否可以删除列表列表中的项目而不会丢失原始引用?

Rom*_*ler 5 .net c#

好的,这有点难以问,但我会尝试.我有一个带有对象的列表(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;
    }
Run Code Online (Sandbox Code Playgroud)

我希望不是那么混乱?我希望我的问题解释得很好.

Jam*_*mes 7

我想我可以看到你的问题在这里.在CopyList你的有效克隆列表即

lot.Wafers = new List<Wafer>(lot.Wafers);
Run Code Online (Sandbox Code Playgroud)

然而,关键的一点,这里要注意的是引用Lot对象仍然是相同的-所以有效地你是克隆和替换Wafers原有的列表属性为好.

你打电话的时候

copyList.RemoveAt(1);
Run Code Online (Sandbox Code Playgroud)

这很好,因为你正在操纵Lot 列表的副本.但是,当你打电话

copyList[0].Wafers.RemoveAt(0);
Run Code Online (Sandbox Code Playgroud)

您正在修改两个列表仍在引用的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)
    });
}
Run Code Online (Sandbox Code Playgroud)

因此,您将丢失Lot对象本身的两个列表中的自动更新,但您仍将保留它以修改单个Wafer对象(因为它们的引用不会更改).

总而言之,您实际要问的是:

如何在具有不同属性引用的同时保留相同的对象引用?

这个问题的答案是 - 你做不到.


Law*_*nce 4

据我所知,没有现成的方法可以让你做你想做的事。这里简单描述一下原因:

List<Lot>最左侧)包含对该Lot对象的引用,该对象又包含对其两个成员变量的引用。

在此输入图像描述

如果您希望按照您的描述传播对列表LotName的 和 组成部分的更改,最简单的解决方案是在列表之间Wafers共享对对象的引用:Lot

在此输入图像描述

现在您可以明白为什么无法Wafers使用此解决方案独立修改列表中的项目 - 您无法摆脱使用相同对象引用的事实!

通过共享参考资料,您将失去控制行为差异的能力。为了实现你想要的,我认为你必须对实例进行深层复制Lot,然后你可以通过某种观察者模式来管理更改的传播。