0

所以我有一个列表,在我的方法中我试图返回一个带有修改的新列表。

但问题是我对线索列表的 ID 所做的更改也正在对我传递的线索列表进行。

        public List<Clue> NewOrderList(List<Clue> clues, int[] ids)
    {
        var newClueOrder = new List<Clue>();

        // For each ID in the given order
        for (var i = 0; i < ids.Length; i++)
        {
            // Get the original clue that matches the given ID
            var clue = clues.First(clue1 => clue1.Id == ids[i]);

            // Add the clue to the new list. 
            newClueOrder.Add(clue);

            // Retain the ID of the clue 
            newClueOrder[i].Id = clues[newClueOrder.Count - 1].Id;
        }

        return newClueOrder;
    }

为什么会这样,最好的解决方案是什么?我见过类似的问题,但老实说,我不太明白解决方案到底是什么。

4

2 回答 2

2

你创建了一个浅拷贝。听起来您想要列表的深层副本。因此,我将首先创建一个深层副本,然后修改您需要修改的任何内容并返回新列表。

您可以序列化和反序列化列表以创建深层副本

当您创建列表的深层副本时,您正在创建新的线索对象,而不仅仅是像在浅层副本中那样引用它们

   public List<Clue> NewOrderList(List<Clue> clues)
   {
        List<Clue> newstringOrder = CreateDeepCopy(clues);

        // Add code to modify list

        return newstringOrder;
   }


public List<Clue> CreateDeepCopy(List<Clue> c)
{
     //Serialization    
     if(c == null)
            return null;
     BinaryFormatter bf = new BinaryFormatter();
     MemoryStream ms = new MemoryStream();
     bf.Serialize(ms, c);

     //Deserialization              
     ms.Position = 0;        
     List<Clue> list = (List<Clue>)bf.Deserialize(ms);       

     return list;    

}
于 2013-04-25T01:15:35.177 回答
1

这是因为Clue是引用类型。您不是在创建新Clue实例,而是在更改现有实例。

为了解决这个问题,您需要使用复制构造函数或某种克隆来获取深层副本:

        // Get the original clue that matches the given ID
        var clue = clues.First(clue1 => clue1.Id == ids[i]);

        // Copy constructor
        var newClue = new Clue(clue);

        // Or, use cloning
        var newClue = clue.Clone();

        // Add the clue to the new list. 
        newClueOrder.Add(newClue);

        // Retain the ID of the clue 
        newClueOrder[i].Id = clues[newClueOrder.Count - 1].Id;

Clone()or 复制构造函数中,您需要复制所有其他非不可变引用类型,而不仅仅是重新分配引用。例如,假设线索有:

public class Clue
{
    ...

    public Clue Clone()
    {
        Clue newClue = new Clue();
        newClue.SomeClassType = this.SomeClassType.Clone(); // You'll need to get a clone or copy of all non-immutable class members as well.
        newClue.Id = this.Id;  // Value types are copied by value, so are safe to assign directly.
        newClue.Name = this.Name;  //If Name is a string, then this is safe too, since they are immutable.
        return newClue;
    }
}
于 2013-04-25T01:15:27.083 回答