我有这个自定义类对象列表:
List<URL> URLs = new List<URL>();
我试图将副本推送到堆栈:
Stack<List<URL>> undo = new Stack<List<URL>>();
List<URL> temp = new List<URL>();
temp.AddRange(new List<URL>(URLs));
undo.Push(temp);
现在每当我从原始(URL)列表中删除一个对象时,堆栈上的一个(temp)就可以了。但是当我从原始(URL)中的对象内的列表中删除列表元素时,相同的元素会消失在堆栈中该对象列表的副本中。
我从URL中删除对象的方式与删除该对象中的列表元素的方式相同。 有谁知道为什么会这样?
答案 0 :(得分:1)
那是因为List基本上是一个数组,即引用类型。他们只会互相参考。
使用扩展方法
制作深层复制public static class ExtensionMethod
{
public static T DeepClone<T>(this T element)
{
MemoryStream m = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(m, element);
m.Position = 0;
return (T)b.Deserialize(m);
}
}
并确保您声明您的网址类
[Serializable]
public class URL
{
//..... Your Class
}
并将其称为
temp.AddRange(URLs.DeepClone().ToList());
答案 1 :(得分:0)
您需要创建克隆
static class Extensions
{
public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
{
return listToClone.Select(item => (T)item.Clone()).ToList();
}
}
答案 2 :(得分:0)
列表或堆栈仅包含引用到它包含的对象。您的列表都包含对相同对象的引用。因此,如果您更改从一个列表到达的对象,那就是从另一个列表中到达的对象。
正如@simply denis建议你可以在创建第二个列表时克隆对象,这样每个列表都有自己的对象副本。
另一种解决方案是使用不可变对象。例如,.NET中的string
类是不可变的。创建字符串后,您无法更改字符串。所有字符串操作例程都返回一个新字符串。不可变类型有效地防止了这种问题,因为任何操作都会自动创建一个新实例。
答案 3 :(得分:0)
那是因为你正在制作一份浅表的副本。您将获得两个列表,其中包含对相同URL
个对象的引用。
(请注意,您实际上制作了两个浅表副本,new List<URL>(URLs)
制作了一个中间副本,您只能从中读取然后丢弃。)
如果需要深层复制,则必须为副本创建新的URL
实例。我不知道你在URL
课程中实现了什么,但基本上是:
List<URL> temp = new List<URL>(URLs.Select(u => u.Clone()));
答案 4 :(得分:0)
这是因为撤消中的网址对象与网址中的网址对象引用的对象相同。因此修改一个影响另一个。您需要做的是制作URL对象的深层副本。如何制作深层副本实际上取决于您的URL类的实现。以下是一般方法:How do you do a deep copy of an object in .NET (C# specifically)?
但请注意,您可能有更好/更有效的方法来克隆URL
对象。您需要先向我们展示该类的实现。