The "C# 4.0 IN A NUTSHELL" 4th edition book by the Albaharis states on page 249: ". . . calling object.ReferenceEquals guarantees normal referential equality."
So, I decided to test this out.
First I tried value types like this.
int aa1 = 5;
int aa2 = aa1;
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And just as I expected, the result was false: object.ReferenceEquals(aa1, aa2) is: False
Life was good. Then I tried a mutable reference type like this.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And just as I expected, the result was true object.ReferenceEquals(sblr1, sblr2) is: True
Life was still good. Then I figured that since it is a mutable reference type, then if I change one variable to null, then both should be null. So I tried the following.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr1 = null;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And I expected them to both be null. But the result I got was False: object.ReferenceEquals(sblr1, sblr2) is: False
Now life was not so good. I thought that if it overrode the memory location of sblr1, then it would be overriding the memory location of sblr2 also.
Then I thought that maybe they were pointing to two different nulls, so I tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr2 = null;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2);
But here, only one was pointing to a null like this. sblr1 == aaa and sblr2 ==
Only one was null.
It was displaying the behavior I'd expect from an immutable reference type like a string object. With a string object, I can do something like this:
string aa1 = "aaX";
string aa2 = "aaX";
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And they will both reference the same thing like this. object.ReferenceEquals(aa1, aa2) is: True because "aaX" only gets written to the assembly once.
But if I do this:
string aa1 = "aaX";
string aa2 = "aaX";
aa1 = null;
MessageBox.Show("After aa1 is null(" + aa1 + "), then aa2 is: " + aa2);
Then they point to different things like this: After aa1 is null (), then aa2 is: aaX
That's because string objects are immutable. The memory location doesn't get overriden. Rather, the variable points to a different location in Heap memory where the new value exists. Changing aa1 to null in the above example means that aa1 will point to a different location on the Heap memory.
Why then is the mutable reference type behaving just the same as the immutable reference type?
Edit 4:03PM and 4:08
I've recently tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
// sblr1 and sblr2 should now both point to the same location on the Heap that has "aaa".
System.Text.StringBuilder sblr2 = sblr1;
System.Text.StringBuilder sblr3 = new System.Text.StringBuilder();
sblr3.Append("bbb");
sblr1 = sblr3;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2 + " and sblr3 == " + sblr3);
Which gave me: sblr1 == bbb and sblr2 == aaa and sblr3 == bbb
That's more like the result I was expecting. I see now, thanks to the comments, that I abscent mindedly expected null to act like a memory location.