令人惊讶的是,String.Clone()
不会像String.Copy()
那样返回字符串的副本。相反,它返回原始字符串'this'
。
我想了解为什么.Net Framework团队选择这样做。
根据MSDN:
ICloneable接口[...]要求您执行 Clone方法返回当前对象实例的副本。
String.Clone()
显然不遵循此指南。
我知道字符串是不可变的,但如果不变性是这里的原因,String.Copy()
也会返回this
,但事实并非如此。
当然,这是一个相当理论化的问题。
答案 0 :(得分:5)
你怎么能发现差异?仅使用object.ReferenceEquals
比较两个引用。但是对字符串的任何语义操作都无法区分。
通过引用比较字符串几乎总是一个错误,因为你很少依赖实习发生或不发生。
此问题不仅适用于String
。如果你有一个不可变的Point
类,你为什么要从Clone
返回一个新的对象?没必要。
IClonable
很少使用且很少有用。如果您希望公开类的用户获取给定实例的副本,则根本不需要继承IClonable
。
答案 1 :(得分:2)
IClonable有点被弃用,因为不清楚“克隆”在整个系统范围内意味着什么(深度,浅层......)。见http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx
参考源使用以下注释记录Clone方法:
//克隆一个字符串没有意义,因为它们是不可变的,所以我们只需返回它。
字符串的实习意味着很难收集字符串(它们可以被多次引用),这意味着真正制作新的字符串副本只会给系统带来压力。此外,实习和复制相互冲突 - 因此实习的一般规则获胜。
答案 2 :(得分:1)
如前所述,由于字符串是只读的,因此Clone()表现得相当合理。实际上,您实际上从不需要两个单独的字符串实例,并且通过不复制,可以保存内存。在极少数情况下,您确实需要副本(出于某种原因,您希望Object.ReferenceEquals
返回false
),您可以改为使用String.Copy()
。
拥有一个只返回this
的方法似乎毫无意义。拥有这种方法的原因是实现ICloneable
,我同意String
应该实现ICloneable
,以便通用代码如
T Foo<T>(T x, ...) where T:ICloneable {/* code that might clone x*/}
可以与String兼容。
我觉得这个方法是public
有点奇怪,因为没有理由直接调用它。如果通过ICloneable
的引用only accessible,那将是有意义的。