【问题标题】:Is there anything wrong with this IClonable implementation这个 IClonable 实现有什么问题吗
【发布时间】:2014-03-18 08:52:17
【问题描述】:

我没有用 C# 编程,但我儿子问我这个实现是否有问题

public class Person : A, IClonable {
....

    public object Clone() {
       return this;
    }
}

我的直觉是它是错误的,因为这个 Clone() 方法实现没有返回任何新对象。我认为 Clone() 方法应该创建一个新对象或调用一个创建新对象的方法然后返回它。这就是我对儿子说的,但我没有做过任何 C# 编程,我变得不确定。有人能解释一下吗?

【问题讨论】:

  • 你是对的:该方法应该创建一个新对象。

标签: c#


【解决方案1】:

我的直觉是这是错误的,因为这个 Clone() 方法 实现不返回任何新对象

那种感觉不会欺骗你。如果要创建它的副本,则需要创建一个新对象。否则,它只是相同的参考,这种实现是毫无意义的和误导性的。

假设你的班级有一个StringProperty

Person p1 = new Person{ StringProperty = "Foo" };
Person p2 = (Person)p1.Clone();
p2.StringProperty = "Bah";
Console.Write(p1.StringProperty); // "Bah"

您会看到,即使我更改了 p2 上的属性,我也会修改另一个实例的 StringProperty,因为它实际上是相同的。

所以你需要这样的东西:

public object Clone() {
    Person p2 = new Person();
    p2.StringProperty = this.StringProperty;
    // ...
    return p2;
}

虽然我更喜欢创建一个不同的方法Copy,因为通常不清楚Clone 做了什么。甚至微软也不建议实施ICloneable

Why should I implement ICloneable in c#?

【讨论】:

    【解决方案2】:

    接口是合约。如果你的类实现了 ICloneable,它promises to:

    支持克隆,即创建一个与现有实例具有相同值的类的新实例

    现在,如果Clone() { return this; } 的作者或其他任何使用此代码的人依赖返回值成为原始代码的克隆,并进行一些可能尚未进行的修改原始对象,你有一个错误要追踪。

    【讨论】:

      【解决方案3】:

      阅读MSDN并检查this examples

      我认为您是对的-您没有创建新对象,因此如果要克隆和更改对象-他将更改原始对象,这不是预期的

      【讨论】:

      • 这不是对 IClonable 的引用
      【解决方案4】:

      请注意,IClonable documentation 不指定深拷贝或浅拷贝。

      它只是指定它应该复制。而这个实现没有。

      【讨论】:

        【解决方案5】:

        要克隆对象试试这个。

        方法一:

        public class Person : ICloneable
        {
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public Address PersonAddress { get; set; }
        
            public object Clone()
            {
                Person newPerson = (Person)this.MemberwiseClone();
                newPerson.PersonAddress = (Address)this.PersonAddress.Clone();
        
                return newPerson;
            }
        }
        
        public class Address : ICloneable
        {
            public int HouseNumber { get; set; }
            public string StreetName { get; set; }
        
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }
        

        方法二:

        public class Person : ICloneable
        {
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public Address PersonAddress { get; set; }
        
            public object Clone()
            {
                object objResult = null;
                using (MemoryStream ms = new MemoryStream())
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(ms, this);
        
                    ms.Position = 0;
                    objResult = bf.Deserialize(ms);
                }
                return objResult;
            }
        }
        

        方法三:

        public class Person : ICloneable
            {
                public string LastName { get; set; }
                public string FirstName { get; set; }
                public Address PersonAddress { get; set; }
        
                public object Clone()
                {
                    var objResult = new Person();
                    objResult.LastName = this.LastName;
                    objResult.FirstName = this.FirstName;
                    objResult.PersonAddress = new Address();
                    objResult.PersonAddress.HouseNumber = this.PersonAddress.HouseNumber;
                    objResult.PersonAddress.StreetName = this.PersonAddress.StreetName;
        
                    return objResult;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-17
          • 2011-09-28
          • 2011-12-14
          • 2017-08-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多