所以我有一个列表,在我的方法中,我试图返回一个带有修改的新列表。
问题是,我对线索列表的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;
}
为什么会这样,最好的解决办法是什么?我见过类似的问题,但说实话,我不太明白解决方案到底是什么。
答案 0 :(得分: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;
}
答案 1 :(得分: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()
或复制构造函数中,您需要复制所有其他非不可变引用类型,不要只重新分配引用。例如,假设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;
}
}