Surprisingly, String.Clone()
doesn\'t return a copy of a string as String.Copy()
would do. Instead, it returns \'this\'
, the original stri
How could you detect the difference? Only by comparing the two references using object.ReferenceEquals
. But by any semantic operation on the string you can't tell the difference.
Comparing strings by reference is almost always a bug to begin with because you can rarely rely on interning to happen or not happen.
This issue does not only apply to String
. If you had an immutable Point
class, why would you return a fresh object from Clone
? No need.
IClonable
is rarely used and rarely useful, anyway. If you want to expose users of your class a way to obtain a copy of a given instance you don't need to inherit from IClonable
at all.
IClonable is somewhat deprecated as it's unclear what "Clone" means from a system-wide standpoint (deep, shallow...). See http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx
The reference source documents the Clone method with the following comment:
// There's no point in cloning a string since they're immutable, so we simply return this.
Interning of strings means that it's hard to collect strings (they can be referenced more than once) which means really making a new copy of string serves only to stress the system. Plus, interning and copying conflict with each other--so the general rule of interning wins.
As has been mentioned, since strings are read-only, Clone() behaves reasonably. You virtually never actually need two separate instances of the string, and by not making a copy, memory is saved. In the very rare case that you actually need a copy (for some reason you want Object.ReferenceEquals
to return false
), you can use String.Copy()
instead.
It may seem pointless to have a method that just returns this
. The reason to have such a method is to implement ICloneable
, and I agree that String
should implement ICloneable
so that generic code like
T Foo<T>(T x, ...) where T:ICloneable {/* code that might clone x*/}
can be compatible with String.
It's a little strange to me that the method is public
, though, since there's no reason to call it directly. It would make sense if it were only accessible through a reference to ICloneable
.