实现克隆方法

时间:2012-10-11 13:53:54

标签: c# collections

我有一个表示一些数据的类和一个集合类(从CollectionBase派生)。当我将一个集合类的实例分配给另一个时,它是通过引用分配的,所以我实现了ICloneable接口。

    public void Add(object item)
    {
        InnerList.Add(item);
    }

    public object Clone()
    {
        MyCollection clone = new MyCollection();

        foreach (MyClass item in this)
        {
            clone.Add(item);
        }

        return clone;
    }

现在一切正常。但是当我浏览元素并将它们逐个添加到克隆实例时,为什么不通过引用添加它们呢? Add方法如何将它添加到InnerList?为什么不通过引用添加?如果我添加这个集合的一个实例,让我们说List并更改列表中的元素怎么办?原始实例是否会被更改?

修改:这是MyClass

public class MyClass
{
    public bool IsEnabled { get; set; }

    public string Parent { get; set; }

    public string Child { get; set; }

    public MyClass()
    {
        IsEnabled = false;
        Parent = string.Empty;
        Child = string.Empty;
    }

    public MyClass(bool isEnabled, string parent, string child)
    {
        IsEnabled = isEnabled;
        Parent = parent;
        Child = child;
    }

    public bool IsValid()
    {
        return (!Parent.Equals(string.Empty) &&
                !Child.Equals(string.Empty));
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        if (!obj.GetType().IsAssignableFrom(this.GetType()))
        {
            return false;
        }

        return ((MyClass)obj).Parent.Equals(Parent) ||
               ((MyClass)obj).Child.Equals(Child);
    }

    public bool Equals(MyClass myClass)
    {
        if (myClass == null)
        {
            return false;
        }

        return myClass.Parent.Equals(Parent) ||
               myClass.Child.Equals(Child);
    }

    public override int GetHashCode()
    {
        return Parent.GetHashCode();
    }
}

编辑2:我做的是

MyClass item = new MyClass(true, "test", "test");
MyCollection collection = new MyCollection();

collection.Add(item);

MyCollection newCollection = new MyCollection();
newCollection = (MyCollection) collection.Clone();

newCollection[0].Parent = "changed";

现在在此之后我预计集合[0] .Parent也将被更改为“已更改”,但它仍然保持不变。是不是通过引用克隆实例添加了它?

3 个答案:

答案 0 :(得分:1)

如果集合中的项目是引用类型,则会通过引用添加它们。如果您添加了克隆集合的内容,则不会修改原始集合。

答案 1 :(得分:1)

这取决于您希望如何实现克隆方法。如果要返回对象的浅表副本,则可以使用Object.MemberwiseClone方法。如果要返回深层副本,则可以使用BinaryFormatter序列化和反序列化对象/集合。这将返回一个新的对象/集合。

答案 2 :(得分:0)

    [Serializable]
    class CustomClass
    {
        int _id;
        string _value;

        public CustomClass(int id, string value)
        {
            _id = id;
            _value = value;
        }
    }

    [Serializable]
    class CustomClassCollection
    {
        private IList<CustomClass> _list = null;

        public CustomClassCollection()
        {
            _list = new List<CustomClass>();
        }

        public void Add(CustomClass a)
        {
            _list.Add(a);
        }
    }



    public static class ObjectCopier
    {
        public static T Clone<T>(this T source)
        {
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable.", "source");
            }

            if (Object.ReferenceEquals(source, null))
            {
                return default(T);
            }

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }
    }

使用它像:

        CustomClassCollection a = new CustomClassCollection();
        CustomClassCollection b = ObjectCopier.Clone<CustomClassCollection>(a);

        a.Add(new CustomClass(1, "A"));
        a.Add(new CustomClass(2, "B"));
        a.Add(new CustomClass(3, "C"));

        b.Add(new CustomClass(1, "A"));
        b.Add(new CustomClass(2, "B"));