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 me
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.
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
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.
A quick search through the BCL for .NET 4.0 shows that the string.Copy
method is called in about a half-dozen places. The usages fall into roughly these categories:
For interop with native functions that can damage the strings passed in to them. If you can't affect the P/Invoke declaration and you can't fix the function being called, string.Copy
is the best choice.
For situations where the string is modified in-place for performance reasons. If you need to convert just a few characters to lowercase in a potentially long string, the only way to do so without copying the string two times and creating additional garbage is to mutate it.
In places where it doesn't seem necessary. It's quite possible that some programmers are more used to Java or C++ strings and don't realize that copying a string in C# is rarely useful.
string a = "abc";
string b = String.Copy(a);
Monitor.Enter(a); // not the same as Monitor.Enter(b);
However
string c = "123";
string d = c;
Monitor.Enter(c); // 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.Append("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.
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).