为什么String.Clone()返回原始字符串而不是它的副本?

时间:2013-12-18 20:08:36

标签: c# .net string icloneable

令人惊讶的是,String.Clone()不会像String.Copy()那样返回字符串的副本。相反,它返回原始字符串'this'

我想了解为什么.Net Framework团队选择这样做。

根据MSDN

  

ICloneable接口[...]要求您执行   Clone方法返回当前对象实例的副本。

String.Clone()显然不遵循此指南。

我知道字符串是不可变的,但如果不变性是这里的原因,String.Copy()也会返回this,但事实并非如此。

当然,这是一个相当理论化的问题。

3 个答案:

答案 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,那将是有意义的。