这个IClonable实现有什么问题吗?

时间:2014-03-18 08:52:18

标签: c#

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

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

    public object Clone() {
       return this;
    }
}

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

5 个答案:

答案 0 :(得分:4)

  

我的直觉是,这是错误的,因为这个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#?

答案 1 :(得分:3)

接口是合同。如果您的类实现了ICloneable,那么promises to

  

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

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

答案 2 :(得分:2)

阅读MSDN并查看this examples

我认为你是对的 - 你不创建新对象,所以如果想要克隆和更改对象 - 他将改变原始对象,这不是预期的

答案 3 :(得分:1)

请注意,IClonable documentation未指定深层或浅层副本。

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

答案 4 :(得分:1)

要克隆对象,请尝试此操作。

方法1:

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();
    }
}

方法2:

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;
    }
}

方法3:

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;
        }
    }