为什么要在 c # 中实现 ICloneable?

你能解释一下为什么我应该从 ICloneable继承并实现 Clone()方法吗?

If I want to do a deep copy, can't I just implement my method? Let's say MyClone()?

我为什么要从 ICloneable继承? 这样做有什么好处? 难道只是为了让代码“更具可读性”吗?

49783 次浏览

You shouldn't. Microsoft recommends against implementing ICloneable because there's no clear indication from the interface whether your Clone method performs a "deep" or "shallow" clone.

有关更多信息,请参见2003年的 Brad Abrams 的博客文章(!)。

ICloneable是 BCL 中一个有争议的伪影。恕我直言,没有真正的理由去实施它。也就是说,如果我要创建一个克隆方法,那么我确实实现了 ICloneable,并且提供了我自己的强类型版本的 Clone

ICloneable的问题在于它从来没有指出 Clone是浅拷贝还是深拷贝,这是两个截然不同的概念。没有 ICloneable<T>的事实可能暗示了微软对 ICloneable 的看法

马特说得对,别用它。创建您自己的 Copy()方法(或类似的名称) ,并使其在您的公共 API 中为 perfectly clear,无论您的方法是创建对象的深拷贝还是浅拷贝。

ICloneable接口 自己并不是非常有用,也就是说,在很多情况下,在不知道对象的任何其他信息的情况下,知道对象是可克隆的并不是很有用。这种情况与 IEnumerableIDisposable非常不同; 在许多情况下,接受 IEnumerable而不知道如何枚举它是有用的。

另一方面,当 ICloneable与其他约束一起作为通用约束应用时,它可能很有用。例如,一个基类可能有用地支持许多派生物,其中一些可以有用地克隆,而另一些则不能。如果基本类型本身暴露了一个公共克隆接口,那么任何不能被克隆的派生类型都会违反 Liskov代换原则。避免此问题的方法是让基类型支持使用 Protected 方法进行克隆,并允许派生类型实现它们认为合适的公共克隆接口。

一旦实现了这一点,一个想要接受一个 WonderfulBase类型的对象并且需要能够克隆它的方法就可以被编码成接受一个支持克隆的 Wonder fulBase 对象(使用一个带有 base-type 和 ICloneable约束的泛型类型参数)。尽管 ICloneable接口本身并不表明是深克隆还是浅克隆,但是 WonderfulBase的文档将表明可克隆的 WonderfulBase应该是深克隆还是浅克隆。从本质上讲,ICloneable接口不会完成定义 ICloneableWonderfulBase所不能完成的任何事情,除了它可以避免为每个不同的可克隆基类定义不同的名称。