对新列表的修改在原列表中重复
本文关键字:列表 修改 新列表 | 更新日期: 2023-09-27 18:10:42
所以我有一个列表,在我的方法中,我试图返回一个带有修改的新列表。
但问题是,我对线索列表的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;
}
为什么会这样,最好的解决方案是什么?我见过类似的问题,但说实话,我不太明白解决方案到底是什么。
您正在创建一个浅副本。听起来你想要一份深度拷贝。因此,我将首先创建一个深拷贝,然后修改任何你需要修改的,并返回新的列表。
您可以序列化和反序列化列表以创建深度副本
当你创建列表的深度拷贝时,你是在创建新的线索对象,而不是像在浅拷贝中那样只是引用它们
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;
}
这是因为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()
或复制构造函数中,您需要复制所有其他非不可变引用类型,而不仅仅是重新分配引用。例如,假设Clue有:
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;
}
}