What role does string immutability play in the explaination of string references to developers?
In one form or another I encounter the following question often (posed, here, in pseudo-code):
String myString = "Hello"
someObject.stringProperty = myString
myString = "World"
Why doesn't someObject.stringProperty now equal "World"?
There seems to be confusion about the role the following statement plays in the explanation of why this is the case:
Strings are Immutable
What do you think?
If you think the statement doesn't apply, I'd ask you this: In a language where strings were mutable, and the assignment operator mutated their actual value (instead of simply changing the reference), would your answer still make sense?
EDIT:
OK, I feel the need to clarify some things:
I'm not confused about how strings, references, or assignments work. I'm perfectly clear on this topic. I'm not asking how strings work. I'm asking "What role does string immutability play in the explaination of string references to developers". We can skip the Ad-Hominem attacks that I must be confused.
I'm looking for a logically rigorous answer for the developer asking the cited question which doesn't contain, or pre-suppose, the immutability of strings.
A categorization of the existing arguments:
String Immutability has nothing to do with it because the references are changing,开发者_Python百科 not the values of the strings
This answer pre-supposes the exact fact I'm asking about.Assignment means assignment of references not assignment of values
Again, this pre-supposes the exact fact I'm asking about. There is no reason this must be the case for strings. It simply is the case for strings for performance and other reasons.
The role played by the statement in the explanation depends on the explanation itself. It could be harmful or useful, depending on the rest of the explanation.
Personally I wouldn't use that statement until fairly late in the explanation (at least these days). The immutability of strings just gets in the way somewhat - as it does with parameter passing explanations. I'd start with an explanation using a mutable class, like this:
House x = new House(Color.Green); // The has a green front door
House y = x;
x = new House(Color.Red);
Console.WriteLine(y.FrontDoorColor); // Still green!
Here I would explain that x
and y
are like pieces of paper with the addresses of houses on. The assignment in the second line doesn't copy a house - it copies the address of a house. The assignment on the third line doesn't change the color of the front door on the first house - it creates a new house, then rubs out the address on the first piece of paper (x
), and writes the new address on. This doesn't change anything about the first house, or the second piece of paper (y
).
I'd then produce a second example:
House x = new House(Color.Green); // The has a green front door
House y = x;
x.FrontDoorColor = Color.Red; // Repainting a front door
Console.WriteLine(y.FrontDoorColor); // Red!
This time there's only one house - if I paint the door of a house and you come to see it with the address I'd given you earlier, you'll see the front door is now red.
So far, so good. Now I could go back to the original example and say that it already looks like the first house snippet rather than the second one, so it behaves the same way. I can then say that string immutability means you can't even write code that looks like the second house example but using strings. So string immutability wouldn't have been immediately relevant to the explanation of the existing code, but it would still have appeared in the same answer.
(I'd also have to point out that although references behave like real-world addresses, I'm not claiming that they're the same as "memory addresses" or pointers. They don't have to be. I'm using the term in a strict analogy to the real world, and that's all. It's a downside of the example, but I don't think it does too much harm.)
I might then also talk about value types, and consider what would have happened if House
had been a value type - as well as discouraging mutable value types.
To know whether or not my answer would still be relevant in a language with mutable strings, we'd need to know more about how string literals behaved. A language which was the same as C# in every way other than the mutability of strings would be an awful language, as you could write:
// Hypothetical bad language
string x = "dog";
x.MutateTo("cat");
Console.WriteLine("dog"); // Prints cat!
That clearly wouldn't be desirable, so presumably the behaviour of string literals would have to change. You also talk about possible changes to the meaning of the assignment operator, etc... it's hard to make concrete statements about a hypothetical language without knowing exactly how it behaves.
It is because the equals sign in computer programming is more of an assignment operator than an "mathematical equality" condition. That the string is immutable has nothing to do with it. This is all about the equals sign being a "assignment" operator rather than a mathematical equivalence constraint.
This means that A = B; and B = C; does not imply that A = C;
instead it means
A has been set to reference the value of B, so B's value is now A's value. B has been set to reference the value of C, so C's value is now B's value, but A's value remains unchanged
If strings were not immutable
String myString = "Hello";
myString.replace(3, "p"); // replace starting at char #3 (the second 'l')
System.out.println(myString); // would print "Help"
But since Strings are immutable;
String myString = "Hello";
myString.replace(3, "p"); // returns a new string "help" which is not assigned to anything
// since the newly returned string was not assigned to anything, it was garbage collected
System.out.println(myString); // would print "Hello"
The explanation is that this example has nothing to do with immutability.
You have two variables originally containing the same value, which for a string means they are pointing to the same object in memory. You then change the value of one of the variables and point it to another object in memory.
It is no different than saying
int a = 4;
int b = a;
a = 5;
Or
string x = "Foo";
string y = x;
x = "Bar";
Or
Foo foo = new Foo() { Bar = 42 };
Foo otherFoo = foo;
foo = new Foo() { Bar = 17; }
The variables momentarily reference the same thing. They are not otherwise inextricably linked for all time. As soon as you point one to something else, their commonality ends.
精彩评论