【问题标题】:Why does String.Clone() returns the original string and not a copy of it?为什么 String.Clone() 返回原始字符串而不是它的副本?
【发布时间】:2014-01-07 04:19:02
【问题描述】:

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

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

根据MSDN

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

String.Clone() 显然没有遵循这个准则。

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

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

【问题讨论】:

  • 由于字符串是不可变的并且是固定的,因此 string.clone 和 string.copy 之间没有区别,因为它们与您的问题有关。
  • 这个问题似乎跑题了,因为它不是关于编程的实践问题,而是一个学术问题。
  • 通过询问“我应该如何在我的自定义不可变类型上实现ICloneable?”,这很容易变成一个实际问题。
  • @hvd 这将使其主要基于意见,并且还可能需要讨论细节;您需要深拷贝是否有令人信服的理由,浅拷贝是否足以满足您的目的,您首先实施ICloneable 的原因是什么?
  • @hvd 规范是否应将其定义为深/浅复制一种意见,这就是您提出的将问题更改为的意见。就目前而言,这个问题不是基于意见,而是出于完全不同的原因而偏离主题。

标签: c# .net string icloneable


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    IClonable 在某种程度上已被弃用,因为从系统范围的角度(深、浅......)不清楚“克隆”是什么意思。见http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx

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

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

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

    【讨论】:

    • 嗯,没有什么比参考来源更能证实其他人的猜测了。
    【解决方案3】:

    如前所述,由于字符串是只读的,因此 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,但对我来说有点奇怪,因为没有理由直接调用它。如果它是 only accessible 通过引用 ICloneable 将是有意义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-04
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多