I was perplexed after executing this piece of code, where strings seems to behave as if they are value types. I am wondering whether the assignment operator is operating on
Whenever you see
variableName = someValue;
that's changing the value of the variable - it's not changing the contents of the object that variable's value refers to.
This behaviour of string is entirely consistent with other reference types, and has nothing to do with immutability. For example:
StringBuilder b1 = new StringBuilder("first");
StringBuilder b2 = b1;
b2 = new StringBuilder("second");
That last line doesn't change anything about b1
- it doesn't change which object it refers to, or the contents of the object it refers to. It just makes b2
refer to a new StringBuilder
.
The only "surprise" here is that strings have special support in the language in the form of literals. While there are important details such as string interning (such that the same string constant appearing in multiple places within the same assembly will always yield references to the same object) this doesn't affect the meaning of the assignment operator.
The first reason is String is an immutable class.
An object qualifies as being called immutable if its value cannot be modified once it has been created. For example, methods that appear to modify a String actually return a new String containing the modification. Developers are modifying strings all the time in their code. This may appear to the developer as mutable - but it is not. What actually happens is your string variable/object has been changed to reference a new string value containing the results of your new string value. For this very reason .NET has the System.Text.StringBuilder class. If you find it necessary to modify the actual contents of a string-like object heavily, such as in a for or foreach loop, use the System.Text.StringBuilder class.
For example:
string x= 123 ;
if you do x= x + abc what it does is it assigns new memory location for 123 and abc. Then adds the two strings and places the computed results in new memory location and points x to it.
if you use System.Text.StringBuilder sb new System.Text.StringBuilder( 123 ); sb.Append( abc ); x sb.ToString();
stringbuilder is mutable class. It just adds the string to same memory location. This way string manipulation is faster.
A string is an object of type String whose value is text. Internally, the text is stored as a readonly collection of Char objects, each of which represents one Unicode character encoded in UTF-16.
You're not changing anything about the object a1 points to, but instead changing which object a1 points to.
(source: morethannothing.co.uk)
Your example replaces "new Person { … }" with a string literal, but the principle is the same.
The difference comes when you're changing properties of the object. Change the property of a value type, and it's not reflected in the original.
(source: morethannothing.co.uk)
Change the property of a reference type, and it is reflected in the original.
p.s. Sorry about the size of the images, they're just from something I had lying around. You can see the full set at http://dev.morethannothing.co.uk/valuevsreference/, which covers value types, reference types, and passing value types by value and by reference, and passing reference types by value and by reference.
There are three semantic types of entities:
If one makes a copy X of a mutable reference Y and then does something with the copy, any mutation performed upon X will affect Y, and vice versa, since X and Y both refer to the same object. By contrast, if one makes a copy XX of a mutable value type instance YY, changes to XX will not affect YY, nor vice versa.
Because the only semantic difference between reference types and value types is the behavior if they are altered after they are copied, immutable reference types are semantically identical to immutable value types. That is not to imply that there aren't sometimes considerable performance advantages to using one over the other.
(*) Meaning value types which can be partially altered without being completely replaced. Point, for example, is mutable because one can change part of it without having to read and rewrite the whole thing. By contrast, Int32 is immutable, since (at least from "safe" code) it's not possible to make any change to an Int32 without rewriting the whole thing.
They don't. You changed the pointer of a2
, not the object it pointed to.
When you are using classes and getting your expected behavior, you must be setting a property of the object, not its reference.
Any other class will behave the same:
Foo a = new Foo(1);
Foo b = a; //a, b point to the same object
b.Value = 4; // change property
Assert.Equals(a.Value, 4); //true - changed for a
b = new Foo(600); // new reference for b
Assert.Equals(a.Value, 4); //true
Assert.Equals(b.Value, 600); //true
If I remember correctly once Erik Lippert wrote on SO that this behavior was chosen so that multihreading is easier and more secure. This way when you store a string in a1, you know that only you can change it. It cannot be changed from other threads for example.