编辑一个列表<>编辑它的克隆

时间:2012-04-28 06:56:14

标签: c#

我有这个自定义类对象列表:

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中删除对象的方式与删除该对象中的列表元素的方式相同。 有谁知道为什么会这样?

5 个答案:

答案 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对象。您需要先向我们展示该类的实现。