【问题标题】:Implementing the clone method实现克隆方法
【发布时间】:2012-10-11 13:53:54
【问题描述】:

我有一个代表一些数据的类和一个集合类(从 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";

在此之后,我预计 collection[0].Parent 也会更改为“已更改”,但它仍然保持不变。不是引用克隆实例添加的吗?

【问题讨论】:

    标签: c# collections


    【解决方案1】:

    如果您的集合中的项目是引用类型,则它们是通过引用添加的。如果你在克隆的集合中添加一些东西,它不会修改原始集合。

    【讨论】:

    • 但是为什么集合是引用类型而我创建的自定义类不是?
    • @hattenn - 应该是。你能分享MyClass的代码吗?
    • 我已添加到问题中。
    • 谢谢。您是如何得出MyClass 不是引用类型的结论的?
    • 我也将其添加到问题中。
    【解决方案2】:

    这取决于您要如何实现克隆方法。如果你想返回对象的浅拷贝,那么你可以使用Object.MemberwiseClone 方法。如果你想返回深拷贝,那么你可以使用BinaryFormatter 来序列化和反序列化对象/集合。这将返回一个新的对象/集合。

    【讨论】:

      【解决方案3】:
          [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"));
      

      【讨论】:

        猜你喜欢
        • 2017-09-01
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        • 2011-02-27
        • 2014-12-19
        • 2023-03-15
        • 2012-05-16
        • 1970-01-01
        相关资源
        最近更新 更多