21

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

我想了解 .Net Framework 团队为何选择这种方式。

根据MSDN

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

String.Clone()显然不遵循此准则。

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

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

4

3 回答 3

5

你怎么能发现差异?仅通过使用比较两个参考object.ReferenceEquals。但是通过对字符串的任何语义操作,您都无法区分。

通过引用比较字符串几乎总是一个错误,因为您很少依赖实习来发生或不发生。

这个问题不仅适用于String. 如果您有一个不可变的Point类,为什么要从 中返回一个新对象Clone?没必要。

IClonable无论如何,很少使用也很少有用。如果您想向您的类的用户公开一种获取给定实例副本的方法,您根本不需要继承IClonable

于 2014-04-11T16:23:43.837 回答
2

IClonable 有点被弃用,因为从系统范围的角度(深,浅......)不清楚“克隆”是什么意思。请参阅http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx

参考源记录了 Clone 方法,并带有以下注释:

// 克隆字符串没有意义,因为它们是不可变的,所以我们只需返回 this。

字符串的实习意味着很难收集字符串(它们可以被多次引用),这意味着真正制作一个新的字符串副本只会给系统带来压力。另外,实习和复制是相互冲突的——所以实习的一般规则获胜。

于 2014-04-11T18:46:06.743 回答
1

如前所述,由于字符串是只读的,因此 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.

于 2014-04-11T18:41:40.897 回答