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