Why does 'String' not have a copy constructor?
-
9 октября 2006 г. 5:55Is there a reason that the 'System.String' type does not have a copy constructor? A 'copy constructor' is a constructor that takes its own type as a parameter.
I would have expected the string type to have copy constructor as it should permit strings to easily share the internal reference to the string data. This would both improve performance and reduce memory consumption as the internal string data object is shared, and not constructed, from the existing string to the new string.
Am I missing something?
Все ответы
-
9 октября 2006 г. 6:12
There is no such thing as "Copy Constructor" in C# so I assume that you want a contructor like
String(String another);
The problem is that it is completly useless. Strings in C# (unlike most of string classes that you can find in C++ for example) are immutable. Once you have create a string object it never changes its value. The result of immutabilty is that making a copy of a string is of no use. Since the original cannot change you can just use it without making a copy.
-
10 октября 2006 г. 21:32
Fortunately there is a mechanism for Strings in C# to "easily share the internal reference to the string data." But you don't need copy constructors to use it. In C#, its simpler.
Look at this code:
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4:5: namespace CSharpConsoleApplication3
6: {7: class Program
8: {9: static void Main(string[] args)
10: {11: String foo = "foo data";
12: String bar = foo;13: Console.WriteLine(ReferenceEquals(foo, bar));14: Console.WriteLine(foo.Equals(bar));15: foo = "a";
16: Console.WriteLine(foo.Equals(bar));17: Console.WriteLine(ReferenceEquals(foo, bar));18: String goober1 = "foo";
19: String goober2 = "foo";
20: Console.WriteLine(ReferenceEquals(goober1, goober2));21: }22: }23: }The thing that you wanted, namely two string variables that point at (reference) the same memory is achieved in lines 11 - 12. In this case, both foo and bar point at the same place in memory. To check, call the ReferenceEquals method, which here returns True in line 13. We can also call the Equals method (line 14) of the String class to see that the two strings are equal in that they both have the same value. That is, they both point at the eight letters that spell "foo data".
Now change the value of foo, as we do in line 15. A C/C++ programmer might then expect that both foo and bar would still reference the same memory, and hence both have the value "a". This is not the case. Lines 16 and 17 both return false. The assignment of "a" to foo broke the connection between the two variables. Intuitively, this is what we would expect. It's only our "deeper understanding" of computer languages that make us see this as odd.
The final twist in this saga is that line 20 also returns true. Here we have assigned two different strings to two different variables. Our expectation is that these two variables should not point at the same place in memory. But line 20 shows that they do reference the same block of memory.
It turns out that C# maintains something called an "intern table." This is a list of strings that are currently referenced. If a new string is created with code like that shown in lines 18 and 19, then the intern table is checked. If your string is already in there, then both variables will point at the same block of memory maintained by the intern table. The string is not duplicated. Again, this is intuitively what we want, but our understanding of computers makes us think that this is not what will happen. C# tries to conform to what we would intuitively expect to happen, not to what we think a computer is likely to do.
Some of the details of the intern table are discussed in this reference to the String Intern method.
-
10 октября 2006 г. 21:50
wow
TOTALLY awesome response . Thank-you!
-
10 октября 2006 г. 23:48Thanks for the replies.
The Copy constructor is the name for a specific type of constructor for a class and could have been used throughout the .NET Framework. I have since read that copy constructors are not used in the .NET Framework as they do not work with C# Interfaces.
To make a copy of an object, the approach should be to implement is the ICloneable interface.
Then, as to be expected, the .NET Framework class 'String' implements 'ICloneable' and has a .Clone() method.
Also, in the String class, the assignment operator has been written so the LHS references the string data of the RHS and will only create a new object if required.

