views:

961

answers:

7

I'm afraid that this is a very silly question, but I must be missing something.

Why might one want to use String.Copy(string)?

The documentation says the method

Creates a new instance of String with the same value as a specified String.

Since strings are immutable in .NET, I'm not sure what's the benefit of using this method, as I'd think that

 string copy = String.Copy(otherString);

would for all practical purposes seem to yield the same result as

 string copy = otherString;

That is, except for whatever internal bookkeeping that's going on, and the fact that copy is not ReferenceEquals to otherString, there are no observable differences - String being an immutable class whose equality is based on value, not identity. (Thanks to @Andrew Hare for pointing out that my original phrasing was not precise enough to indicate that I realized there was a difference between Copying and not, but was concerned about the perceived lack of useful difference.)

Of course when passed a null argument, Copy throws an ArgumentNullException, and the "new instance" might consume more memory. The latter hardly seems like a benefit, and I'm not sure that the null check is a big enough bonus to warrant a whole Copy method.

Thanks.

+13  A: 

String.Copy returns a new String and does not yield the same results as

String copy = otherString;

Try this:

using System;

class Program
{
    static void Main()
    {
     String test = "test";
     String test2 = test;
     String test3 = String.Copy(test);

     Console.WriteLine(Object.ReferenceEquals(test, test2));
     Console.WriteLine(Object.ReferenceEquals(test, test3));

     Console.ReadLine();
    }
}

When you set test2 = test these references point to the same String. The Copy function returns a new String reference that has the same contents but as a different object on the heap.


Edit: There are a lot of folks that are pretty upset that I did not answer the OP's question. I believe that I did answer the question by correcting an incorrect premise in the question itself. Here is an analogous (if not oversimplified) question and answer that will hopefully illustrate my point:

Question:

I have observed that my car has two doors, one on each side of the car. I believe it to be true that regardless of which door I use I will end up sitting in the driver's seat. What is the purpose of the other door?

Answer:

Actually it is not true that if you use either door you will end up in the driver's seat. If you use the driver's side door you will end up in the driver's seat and if you use the passenger's side door you will end up in the passenger's seat.

Now in this example you could argue that the answer is not really an answer as the question was "what is the purpose of the passenger's side door?". But since that question was wholly based on a misconception of the how the doors worked does it not follow that the refutation of the premise will shed new light on the purpose of the other door by deduction?

Andrew Hare
The question wasn't "What does it do" but "Why would I use it?"
Peter Morris
I think the point was: "what is the use of duplicating immutable information?" instead of re-using it.
PhiLho
The entire question was based on the false premise that "string one = String.Copy(two);" and "string one = two;" are equivalent statements. I was simply pointing out that the poster was incorrect.
Andrew Hare
OP was "Why might one want to use String.Copy(string)?" OP recognizes that it makes a copy, but given that .Net strings are immutable, what good is that?
abelenky
If the OP recognized that then why does the question contain this statement: "string copy = String.Copy(otherString); would yield the same result as string copy = otherString;"?
Andrew Hare
Busted. +1 to Hare.
Will
This may correct a mistake in the OP's question...but that's not the same thing as *answering* the question, which you *didn't* do.
Kyralessa
Clearly the OP was interested in why would one use it - not the mechanical differences. Even though the two statements are not equivalent (strictly speaking), they are for most intents and purposes, and the OP was looking for the use cases where the difference mattered.
Michael Burr
@Michael Burr - There is a great difference between having two references to the same String and two references to two different Strings with the same contents. When are the OP's statements ever equivalent? When does a string reference assignment ever the same as a String.Copy()?
Andrew Hare
Two separate string references that have the same 'contents' are for *most purposes* equivalent because String.Equals() is not reference equality, it's value equality.
Michael Burr
Andrew Hare - you're right that my "yield the same result as" is overly loose. I'd edited from an original phrasing that emphasized how I was concerned about the behaviour of copy. I should've reread more carefully. Nevertheless, I'm on the side of "pointing out a mistake != answering the question".
Blair Conrad
@Blair - I apologize for not answering your question as you hoped; I didn't even intend for my answer to be "the answer" to the question. I was merely pointing out the difference :)
Andrew Hare
Andrew, your analogy is a good one...because you didn't answer the question there either. One possible answer is: "Having two doors makes it easier for two people to get in or out of the car, because each can use his own door and enters closer to his own seat."...
Kyralessa
And another possible answer is: "If you enter by the left-hand door, you won't have to climb over the gear shift or other apparatus in the middle of the car." Logically a car *could* have just one door. A good answer explains why more than one is useful.
Kyralessa
@Michael Burr - Good point! I was focusing mainly on identity rather than equality.
Andrew Hare
So if so many people think this answer is incorrect, why does it have 12 votes? Why do some perfectly valid answers get negative votes and obviously incorrect answers get positive ones?This site confuses me!
Peter Morris
+17  A: 

With String.Copy you are actually allocating new memory and copying the characters from one string to another; you get a completely new instance as opposed to having both variables being the same instance. This may matter if you use the string with unmanaged code which deals with the memory locations directly and can mutate the string.

tvanfosson
That's was my guess. It'd be freaky as hell if the text throughout your whole application starts changing randomly...
Will
While this is the first thing that came to mind for me, it sure sounds like a bug waiting to happen - if you're performing interop with unmanaged code that's changing a string, you should probably be using a StringBuilder instead.
Michael Burr
Sounds like a bug pattern if you tried to modify a immutable object.
Dennis Cheung
I never said that I would do this and I can't think of any examples where I would be tempted to do this. On the other hand if I needed to use unmanaged code that deals with strings and it needed to modify it in place, I'd probably make a copy of my string and pass it that to avoid the errors.
tvanfosson
@tvanfosson - I didn't mean to imply that this was something you endorsed. I understood that your answer was a hypothetical possible reason. I apologize if my comment leads others to misunderstand.
Michael Burr
Yes, that's the piece I was missing - what happens when you give your memory away to external code. At work we pass strings as unmodifiable parameters to unmanaged code, but use StringBuffers when we expect things to be mangled - it wouldn't have occurred to me to use String for that. Thanks.
Blair Conrad
I'd say this answer means that there is no sane use for String.Copy!
Daniel Earwicker
+5  A: 
string a = "abc";
string b = String.Copy(a);

Monitor.Enter(a); is not the same as Monitor.Enter(b);

However

string c = "123";
string d = c;
Monitor.Enter(c); is the same as Monitor.Enter(d);

As to way anyone will care, I think it is there for completeness.


Also

StringBuilder sb = new StringBuilder(100);
sb.Apend("abc");
string a = sb.ToString();
string b = String.Copy(a);

I think "a" will take up more RAM then "b", as "a" points to the buffer of size 100 that the StringBuilder created. (Look at the inside of the StringBuilder.ToString() method)


I think StringBuilder makes use of String.Copy() and being part of the .NET framework StringBuilder does change the contents of the string. So a string is not always immutable.

Ian Ringrose
It isn't necessary for StringBuilder to ever modify a string. Internally it could use a List<char> that would efficiently grow in size, and then the ToString method would allocate a string from the contents of the list.
Daniel Earwicker
A: 
string a = "test";
string b = a;
//Object.ReferenceEquals(a,b) is true
a += "more";
//Object.ReferenceEquals(a,b) is now false !

auto-change detection ?

No, appending to the string creates a new instance of a string (since strings are immutable). After appending "a" will point to another instance.
moose-in-the-jungle
A: 

I am not sure how String being implemented in .NET, but I think Java is a good reference.

In Java, new String(str) also do what String.copy(str); do, allocate a new String with same value.

It seem useless but it is very useful in memory optimization.

String contains a char[] with offset and length in the implementation. If you do a something like a substring, it won't do a memory copy but return a new String instance sharing same char[]. In many cases, this pattern will save a lot of memory copy and allocation. However, if you substring a small piece within a long large String. It will still reference to large char[] even the original large String is able to be GC.

String longString = // read 1MB text from a text file
String memoryLeak = largeString.substring(100,102); 
largeString=null;
// memoryLeak will be sized 1MB in the memory
String smaller = new String(largeString.substring(100,102));
// smaller will be only few bytes in the memory

It can force the new String object allocate it's own char[] to prevent hidden memory leak/waste.

Dennis Cheung
This is not how it works. Just assuming that .NET has the same implementation as Java isn't right either. On top of that, the answer has nothing to do with the question.What happens when you .Substring(100, 102): a new string with length 102 is created that contains characters 100 ... 201
Sander Rijken
A: 

In addition to what tvanfosson said (I don't think you can access the buffer used by a managed string from unmanaged code... I know it would be difficult, at least), I believe there may be a difference if the string is used as the object to do a lock on for multithreaded functionality.

For instance...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = example1;

    public void ExampleMethod1()
    {
     lock (example1)
     {
      Console.WriteLine("Locked example 1");
      //do stuff...
     }
    }

    public void ExampleMethod2()
    {
     lock (example2)
     {
      Console.WriteLine("Locked example 2");
      //do stuff
     }
    }
}

I believe if the two example methods are run in parallel, they will be locking the same object and thus one will not be able to execute while the other is inside its lock block.

However if you change it to this...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = string.Copy(example1);

    public void ExampleMethod1()
    {
     lock (example1)
     {
      Console.WriteLine("Locked example 1");
      //do stuff...
     }
    }

    public void ExampleMethod2()
    {
     lock (example2)
     {
      Console.WriteLine("Locked example 2");
      //do stuff
     }
    }
}

Then I believe they will only block execution of other threads executing the same method (i.e. any threads executing ExampleMethod1 will be locked until each completes, but they will not interfere with threads running ExampleMethod2).

Not sure this is a useful difference, since there are better mechanisms for synchronization (I don't think locking strings is a very good idea).

+4  A: 

Here's one piece of the puzzle. It doesn't explain why you would want to do it, but it does help explain a functional difference.

If you pin the string using the fixed keyword, the contents would be mutable. Off the top of my head, I can't think of a situation in which you would want to do this, but it is possible.

string original = "Hello World";
string refCopy = original;
string deepCopy = String.Copy(original);

fixed(char* pStr = original)
{
   *pStr = 'J';
}

Console.WriteLine(original);
Console.WriteLine(refCopy);
Console.WriteLine(deepCopy);


Output:

Jello World
Jello World
Hello World
Kennet Belenky