为什么我应该在 C# 中实现 ICloneable?
-
22-08-2019 - |
题
你能向我解释一下为什么我应该继承 ICloneable
并实施 Clone()
方法?
如果我想做深拷贝,我不能只实现我的方法吗?比方说 MyClone()
?
为什么我要继承 ICloneable
?有什么优点?这只是让代码“更具可读性”的问题吗?
解决方案
你不应该。微软建议不要实施 ICloneable
因为界面上没有明确指示您是否 Clone
方法执行“深”或“浅”克隆。
看 布拉德·艾布拉姆斯的这篇博文 早在 2003 年(!)就可以了解更多信息。
其他提示
这 ICloneable
界面 通过它自己 不是很有用,也就是说,在不知道任何其他信息的情况下知道对象是可克隆的确实没有太多用处。这是与例如非常不同的情况。 IEnumerable
或者 IDisposable
;在很多情况下,接受一个是有用的 IEnumerable
除了如何枚举之外不知道任何事情。
另一方面, ICloneable
当作为通用约束与其他约束一起应用时可能很有用。例如,一个基类可能会有效地支持许多派生类,其中一些可以有效地克隆,而另一些则不能。如果基类型本身暴露了公共克隆接口,那么任何无法克隆的派生类型都将违反里氏替换原则。避免此问题的方法是让基类型支持使用受保护方法进行克隆,并允许派生类型实现它们认为合适的公共克隆接口。
一旦完成,一个想要接受 a 对象的方法 WonderfulBase
类型,并且需要能够克隆它,可以编码为接受支持克隆的 WonderfulBase 对象(使用具有基类型和 ICloneable
限制)。虽然 ICloneable
接口本身并不指示深克隆或浅克隆,文档 WonderfulBase
将指示是否可克隆 WonderfulBase
应该是深克隆或浅克隆。本质上, ICloneable
接口不会完成任何通过定义无法完成的事情 ICloneableWonderfulBase
, ,除了它可以避免为每个不同的可克隆基类定义不同的名称。
ICloneable
是 BCL 中备受争议的工件之一。恕我直言,没有真正的理由来实施它。话虽如此,如果我要创建一个克隆方法,那么我会实现 ICloneable
, ,我提供了我自己的强类型版本 Clone
.
问题与 ICloneable
是否从未表明过 Clone
是浅拷贝还是深拷贝,这是非常不同的事情。事实是没有 ICloneable<T>
可能表明了微软对 ICloneable 的想法
马特是对的,不要使用它。创建您自己的 Copy()
方法(或类似名称)并使其 完全清楚 在您的公共 API 中,无论您的方法是创建对象的深副本还是浅副本。