3

I've just come across a block like this while browsing through legacy code :

object exeName = _connectionSettings.ApplicationName.Clone();
RandomFunction(exeName);

It seemed useless to me at first, but it made me wonder. Is there a fundamental difference between:

var copiedString = initialString;
var copiedString = initialString.Clone();
var copiedString = string.Copy(initialString);

I've created a basic unit test that seems to show there is none since it behaves the same way regardless of the method used (initial affectation of copiedString, change of the initialString, assertion of copiedString value) . Am I missing something?

Keysharpener
  • 486
  • 3
  • 14
  • http://stackoverflow.com/questions/2200409/what-is-the-difference-between-copying-and-cloning – Rahul Nov 13 '14 at 09:30
  • http://stackoverflow.com/questions/3465377/whats-the-use-of-string-clone and http://stackoverflow.com/questions/2334527/when-deep-cloning-use-string-copy-or-str1-str2 – Soner Gönül Nov 13 '14 at 09:32
  • Sounds like it's just a bad legacy codebase. – Jon Skeet Nov 13 '14 at 09:35
  • Thanks for the links, but I understand the difference for standard reference types. Though in the case of `String` I don't understand the difference because it behaves as a value type. – Keysharpener Nov 13 '14 at 09:45

4 Answers4

5

Using Reflector to look at the implementation of String.Clone() reveals this:

public object Clone()
{
    return this;
}

So the answer is "No, there is no difference between assigning and cloning for a string".

However, Copy() is somewhat different:

public static unsafe string Copy(string str)
{
    if (str == null)
    {
        throw new ArgumentNullException("str");
    }
    int length = str.Length;
    string str2 = FastAllocateString(length);
    fixed (char* chRef = &str2.m_firstChar)
    {
        fixed (char* chRef2 = &str.m_firstChar)
        {
            wstrcpy(chRef, chRef2, length);
        }
    }
    return str2;
}

This is actually making a copy - but since strings are immutable, it's not very useful anyway.

But - and this is important - Copy() will return a DIFFERENT REFERENCE from the original string, and Clone() will return the SAME REFERENCE as the original string.

Another thing to be aware of is string interning which causes strings with identical values to share the data (and therefore have the same string reference).

For example, the following code will print "Same!":

string s1 = "Hello";
string s2 = "Hello";

if (ReferenceEquals(s1, s2))
    Console.WriteLine("Same!");

But the following code will print "Not same!", even though the string values are the same:

string s1 = "Hello";
string s2 = "He";
string s3 = "llo";
string s4 = s2 + s3;

if (!ReferenceEquals(s1, s4))
    Console.WriteLine("Not Same!");

We can explicitly intern s4, so that the following prints "Same!":

string s1 = "Hello";
string s2 = "He";
string s3 = "llo";
string s4 = s2 + s3;

s4 = string.Intern(s4);

if (ReferenceEquals(s1, s4))
    Console.WriteLine("Same!");
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • In addition: [Looking at the source code of Clone method](http://referencesource.microsoft.com/#mscorlib/system/string.cs,788b867900542bbe) there is comment: `There's no point in cloning a string since they're immutable, so we simply return this.` – Renatas M. Nov 13 '14 at 09:55
  • If we clone or assign a string1 to a string2, they will share the same reference (and value) until one of them is reassigned, therefore creating a new reference and value? – Keysharpener Nov 13 '14 at 09:58
  • @Keysharpener Yep, but if two strings have the same value, it's entirely possible that they will have the same reference! I will update my answer to include an example. – Matthew Watson Nov 13 '14 at 10:45
  • Do you have an example when sharing a reference can be an issue? – Keysharpener Nov 13 '14 at 10:47
  • @Keysharpener It *should* never be an issue, because strings are immutable. However, one can envisage code which is for some reason calling `ReferenceEquals()` and doing something different depending on the return value. It would be bad code, but I can imagine it existing. – Matthew Watson Nov 13 '14 at 10:54
0

String.Clone() does nothing but return the reference to the same string (see here) But since strings in C# are immutable anyway, there's no difference between all three methods you've specified.

EranGo
  • 13
  • 2
0

Since the CLR implements immutable strings, and treats strings like values, semantically, the only time it would ever be an issue in correct code is outside of the managed code sandbox.

In context of managed code, strings should be simply assigned, just like int and byte and float.

codenheim
  • 20,467
  • 1
  • 59
  • 80
0

Since the CLR implements immutable strings, and treats strings like values, semantically, the only time it would ever be an issue in correct code is outside of the managed code sandbox, and even so, correct code would properly consider all aspects of CLR strings (as in 2 strings may refer to the same "value").

In context of managed code, strings should be simply assigned, just like int and byte and float.

codenheim
  • 20,467
  • 1
  • 59
  • 80