0

I have this doubt related to C# "String" reference types .

The following code:

string s = "lana del rey" 
string d = s;
s = "elvis presley";
Console.Writeline(d);

Why the Output is not "elvis presley" ? If d is pointing to the same memory location of s ?

Could you please explain this?

A more detailed explanation of my initial question:

All your answers were very useful. That question came to me with this common code sample frecuently used to explain difference between value types and reference types:

class Rectangle
{
    public double Length { get; set; }
}

struct Point 
{
    public double X, Y;
}

Point p1 = new Point();
p1.X = 10;
p1.Y = 20;
Point p2 = p1;
p2.X = 100;
Console.WriteLine(“p1.X = {0}”, p1.X);

Rectangle rect1 = new Rectangle
{ Length = 10.0, Width = 20.0 };
Rectangle rect2 = rect1;
rect2.Length = 100.0;
Console.WriteLine(“rect1.Length = {0}”,rect1.Length);

In this case, the second Console.WriteLine statement will output: “rect1.Length = 100”

In this case class is reference type, struct is value type. How can I demostrate the same reference type behaviour using a string ?

Thanks in advance.

Alberto Montellano
  • 5,886
  • 7
  • 37
  • 53
  • You asked the same question a few minutes ago, and then deleted your question. Did the "Related" links not help you? – Tim S. Jan 15 '14 at 20:51
  • Suppose you said instead `int x = 1; int y = x; x = 2; Console.WriteLine(y);` Do you expect `y` to be `1` or `2`? `int y = x` does not mean "`y` is now an alias of `x`". It means "the current value of `y` is changed to be the current value of `x`". No permanent relationship is formed between them. The same is true of your `s` and `d`. – Eric Lippert Jan 15 '14 at 21:12
  • @EricLippert I think he confused reference with pointer, as mentioned by zerkms. – crush Jan 15 '14 at 21:14
  • If you have a new question then you should ask a new question, rather than editing a new question into an existing (and already answered) question. – Servy Jan 15 '14 at 22:10
  • Thank you for all your feedback @Servy – Alberto Montellano Jan 15 '14 at 22:11

6 Answers6

6

It has nothing to do with mutability

string s = "lana del rey" 
string d = s;

Here 2 variables s and d refer to the same object in memory.

s = "elvis presley";

here in the right part of the statement the new object is allocated and initialized with "elvis presley" and assigned to s. So now s refers to another object. And while we haven't change the d reference value - it continues referring to the "lana del rey" as it originally did.

Now the real life analogy:

There are 2 people (A and B) pointing using their fingers to a building far away. They are independent to each other, and don't even see what another is pointing to. Then A decides to start pointing to another building. As long as they aren't connected to each other - now A points to another building, and B continues pointing to the original building (since no one asked them to stop doing that)

PS: what you probably are confusing is the concept behind a pointer and a reference. Not sure if it makes sense to explain it here since you might be confused even more. But now at least you might google for the corresponding keywords.

zerkms
  • 249,484
  • 69
  • 436
  • 539
  • It seemed from the phrasing and nature of the question that the author understood that `s` was set to a reference of `d`. What he didn't understand was that `"elvis presley"` was creating a new `string` instance, rather than setting the value of the instance that `s` referenced. This is why `string` immutability was brought up in so many answers: to illustrate why a new `string` instance was being created. – crush Jan 15 '14 at 20:58
  • @crush: I don't see how it's relevant - neither of the strings is modified or even attempted to :-S – zerkms Jan 15 '14 at 21:00
  • @crush: And mutable reference types exhibit the same behavior, no? Typing "x = y", where x is a reference type (mutable or not) never means "modify the object x refers to". – Aaron Jan 15 '14 at 21:04
  • It seems to me that the author thought that `s = "elvis presley"` was modifying the `string` instance that was created with `string s = "lana del rey";`. Yes, mutable reference types exhibit the same behavior. But the author didn't understand that a new reference was being created. He thought that he was just setting the value of the existing reference. That's the conclusion I came to at least reading the way this question was setup. It seemed evident in his sample code that he knew `s = d` was setting these two references to each other. – crush Jan 15 '14 at 21:06
  • @crush: "But the author didn't understand that a new reference was being created" --- and creating a new instance still has nothing to do with mutability. – zerkms Jan 15 '14 at 21:07
  • @zerkms Mutability was brought up as more of an explanation as to why `s = "elvis presley"` wasn't modifying the existing instance, but creating the new one. That is how I interpreted the author's confusion. If `s = "elvis presley"` was setting the value of the string instance referenced by `s`, then `Console.WriteLine(d)` would've echo'd `elvis presley`. Your hypothesis that the author was confusing pointers and references makes more sense, though. – crush Jan 15 '14 at 21:17
  • please , see my edited question, or below question. – Alberto Montellano Jan 15 '14 at 22:06
5

Strings in C# are immutable; that means they cannot change. When you say s = "elvis presley" you are creating a new string and assigning its reference to s; this does not affect the reference saved to d which still points to the original string.

TypeIA
  • 16,916
  • 1
  • 38
  • 52
  • 1
    Even for mutable types the behaviour would be the same. `s` is a reference, not a pointer. – zerkms Jan 15 '14 at 20:52
  • So String is like an exception of Reference Type? – Alberto Montellano Jan 15 '14 at 20:59
  • @AlbertoMontellano No. There are lots and lots of immutable reference types (and you can make as many more as you want), there is noting at all exceptional about them. – Servy Jan 15 '14 at 20:59
  • @AlbertoMontellano Not really (it is an exceptional reference type, but not in the way you mean). Anytime you assign to a variable of a reference type, you are simply changing the object that the variable references. You aren't modifying the original object. The original object is still there and other variables might reference it (if not, the object is eligible for garbage collection). – TypeIA Jan 15 '14 at 21:01
3

Strings are immutable. s = "elvis presley" is actually creating a new string and assigning it's reference to the variable s. While the variable d still references the first string "lana del rey".

crush
  • 16,713
  • 9
  • 59
  • 100
  • in that case String behaves as a Value Type? creating a copy of the value? – Alberto Montellano Jan 15 '14 at 20:53
  • @AlbertoMontellano No it doesn't behave like a value type, it behaves like a reference type, because that's exactly what it is. You're not creating a copy of the value, you're creating a copy of the *reference*. – Servy Jan 15 '14 at 20:59
3

Let's look at your code line by line

string s = "lana del rey";

With this line, you created a string object lana del rey referenced by s

string d = s;

with this line, you created a reference called d which referenced to same object in memory (which is lana del rey in this case) with s

s = "elvis presley";

With this line, you created a new string object elvis presley and referenced by s (s doesn't reference anymore lana del rey)

Console.Writeline(d);

Since d still reference to lana del rey, it prints lana del rey.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
0

Strings are handled differently than regular reference types, this is essentially what the compiler does:

string s = new String("lana del rey");
string d = new String(s);
s = new String("elvis presley");
Console.Writeline(d);

The point is a "string reference" points to the string VALUE of s. Any time a NEW string is created and referenced that is a new string and any "references" to the original value are still intact.

T McKeown
  • 12,971
  • 1
  • 25
  • 32
  • my point is a string reference points to the string VALUE of s. Any time a NEW string is created and referenced that is a new string and any "references" to the original value are still intact. – T McKeown Jan 15 '14 at 21:05
  • And yet that point isn't actually in your answer. It's probably better to be explicit about it. I doubt someone at the OP's skill level would infer that from seeing that code. – Servy Jan 15 '14 at 21:06
  • to boil it down EVERY string assignment is a NEW string, how else would you explain it? – T McKeown Jan 15 '14 at 21:06
  • I'm just trying to make some points here... I will edit my answer. =) – T McKeown Jan 15 '14 at 21:07
  • More or less the way you did in your first comment. I'm just saying that comment should have been in your answer, not a comment. – Servy Jan 15 '14 at 21:07
  • "Strings are handled differently than regular reference types" --- are they actually? How so? – zerkms Jan 15 '14 at 21:08
  • Yes, if you create 2 string variables and assign a value to each of them of "Hello" they are pointing to the SAME value. There is a reserved area of memory dedicated to string storage and is the reason that string concatenation is so expensive, hence StringBuilder(). – T McKeown Jan 15 '14 at 21:11
  • that is why logic like: if( "hello" == "hello" ) works implicitly, those 2 strings are the SAME value/hashcode – T McKeown Jan 15 '14 at 21:12
  • @zerkms They are different in that they have a compile time literal value besides `null`. There is direct compiler support for the type trough that. There is also an alias for it `string`. Beyond that, it's a regular reference type. – Servy Jan 15 '14 at 21:12
  • @TMcKeown That works because `==` is overloaded to compare the values of the strings, not the references. Interning is the reason `object.ReferenceEquals("hi","hi")` returns true (if iterning is enabled). – Servy Jan 15 '14 at 21:13
  • "hi" and "hi" are pointing to the same reference. Are you saying that is not true? – T McKeown Jan 15 '14 at 21:18
  • I think you are agreeing with me... http://www.yoda.arachsys.com/csharp/strings.html – T McKeown Jan 15 '14 at 21:19
  • @TMcKeown They are pointing to the same reference, but that's not why `"hi" == "hi"` returns true. It would return true even if they weren't interned. `"hi" == new string("hi")` *also* returns true, despite the fact that they're referring to different references. – Servy Jan 15 '14 at 21:28
  • ah, you are saying that because they are interned they are the same ref... but even if they were not they would be the same because the equality operator is overridden to support a string value match yes? I like talking to you... very knowledgeable. – T McKeown Jan 15 '14 at 21:30
0

From Microsoft .NET Framework 2.0 Application Development Foundation 70 536 book:

"Because reference types represent the address of data rather than the data itself, assigning one reference variable to another doesn’t copy the data. Instead, assigning a reference variable to another instance merely creates a second copy of the reference, which refers to the same memory location on the heap as the original variable."

Then I think:

string s = "lana del rey"; // (creates a reference to the memory location X)
string d = s; // (creates a copy of the reference to the same memory location X)
d = "elvis presley"; // (creates a new reference to the new memory location Y)
Alberto Montellano
  • 5,886
  • 7
  • 37
  • 53