You've misunderstood what you've read. Yes, strings are immutable. That means you cannot change an existing string. This won't work:
string x = "Hello";
x[3] = 'q';
When you're concatenating strings, you get a new one:
string a = "a";
string b = "b";
string c = a+b; // You get a new string and a and b are unchanged.
Even when you're self-concatenating, you get a new string:
string a = "a";
a += "b"; // The same as a = a + "b" and yields a new string.
But assigning to a variable (or passing to a function, or returning from a function, etc) does NOT create a new string.
Strings are "reference types". That means that this variable:
string a = "Hello";
Is just a reference to the string. Doing this:
string b = a;
Just assigns the reference to the variable. It does not alter the string.
Or, to put it in C terms: Reference variables are pointers to objects. Consider:
string a = "Hello"; // a now points to the string object
string b = a; // b now points to the same object.
What the immutability means is that you cannot change the memory that the pointer points to (the string object itself). But the pointer variable is as changeable as ever. You can assign a different address to it.
To return to your original example:
string first = "hello"; // Allocates memory for "hello" and points first to it.
string second = "Bye"; // Allocates memory for "Bye" and points second to it.
first = second; // Assigns the address of second to first.
In the end, both first
and second
point to the same address, which is the address of the string Bye
. The memory of the string hello
is now unreferenced (there are no pointers to it, it's unreachable). The garbage collector will reclaim it sometime later.
Added: Yet another analogy with C. String variables .NET are somewhat like this:
const char* str;
It's a pointer to a constant. You can change the pointer, but you cannot change the stuff that it points to.
Added 2: You should read up on Value Types vs Reference Types in .NET. In a nutshell, value types are all struct
types, and reference types are all class
types. Value types get copied on assignment (or when passed/returned from a function); reference types are pointers.
Note that there is one unintuitive piece here. The class object
, which is the base class of ALL types, is a reference type. Yet Value Types inherit from it, and you can assign a Value Type to a variable of type object
. If you do it, this will cause something called boxing and it involves making a copy of the value, so it's a bit of an expensive operation.