这个IClonable实现有什么问题吗?
本文关键字:问题 什么 IClonable 实现 这个 | 更新日期: 2023-09-27 17:50:53
我没有在c#中编程,但是我的儿子问我这个实现是否有什么问题
public class Person : A, IClonable {
....
public object Clone() {
return this;
}
}
我的直觉是,这是错误的,因为这个Clone()方法实现不返回任何新对象。我认为Clone()方法应该创建一个新对象或调用一个创建新对象然后返回它的方法。这就是我对儿子说的话,但没有做过任何c#编程,我变得不确定。有谁能解释一下吗
我的直觉是,这是错误的,因为这个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
。
为什么我要在c#中实现iclonable ?
接口是契约。如果你的类实现了iclonable,它承诺:
支持克隆,它创建一个与现有实例值相同的类的新实例。
现在,如果Clone() { return this; }
的作者,或使用此代码的任何人,依赖于的返回值是原始的克隆,并进行了一些可能未对原始对象进行的修改,那么您就有一个bug需要跟踪。
阅读MSDN并检查此示例
我认为你是对的-你不创建新的对象,所以如果一个人想克隆和改变对象-他会改变原来的对象,这不是预期的
请注意,IClonable文档没有指定深拷贝或浅拷贝。
它只是指定它应该复制。而这个实现没有。
要克隆对象,请尝试此操作。
方法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;
}
}