4 Stimmen

Welche Rolle spielt die Unveränderlichkeit von Zeichenketten bei der Erläuterung von Zeichenkettenreferenzen für Entwickler?

In der einen oder anderen Form stoße ich oft auf die folgende Frage (hier in Pseudocode gestellt):

String myString = "Hello"
someObject.stringProperty = myString
myString = "World"

Warum ist someObject.stringProperty jetzt nicht gleich "World"?

Es scheint Verwirrung darüber zu herrschen, welche Rolle die folgende Aussage bei der Erklärung spielt, warum dies der Fall ist:

Strings sind unveränderlich

Was meinen Sie dazu?

Wenn Sie glauben, dass diese Aussage nicht zutrifft, möchte ich Sie Folgendes fragen: In einer Sprache, in der Zeichenketten waren veränderbar sind und der Zuweisungsoperator ihren tatsächlichen Wert verändert (anstatt einfach nur die Referenz zu ändern), würde Ihre Antwort dann immer noch Sinn machen?

EDITAR:

OK, ich habe das Gefühl, dass ich einige Dinge klarstellen muss:

  1. Ich bin nicht verwirrt darüber, wie Zeichenketten, Referenzen oder Zuweisungen funktionieren. Ich bin mir über dieses Thema vollkommen im Klaren. Ich frage nicht, wie Strings funktionieren. Ich frage: "Welche Rolle spielt die Unveränderlichkeit von Zeichenketten bei der Erklärung von Zeichenkettenreferenzen für Entwickler". Wir können uns die Ad-Hominem-Angriffe sparen, dass ich verwirrt sein muss.

  2. Ich suche nach einer logisch strengen Antwort für den Entwickler, der die zitierte Frage stellt, die die Unveränderlichkeit von Zeichenketten nicht beinhaltet oder voraussetzt.

Eine Kategorisierung der vorhandenen Argumente:

  1. String Immutability has nothing to do with it because the references are changing, not the values of the strings Diese Antwort setzt genau die Tatsache voraus, nach der ich frage.

  2. Assignment means assignment of references not assignment of values Dies setzt wiederum genau die Tatsache voraus, nach der ich frage. Es gibt keinen Grund für diese muss bei Zeichenketten der Fall sein. Es ist einfach ist der Fall für Saiten aus Leistungs- und anderen Gründen.

4voto

Edwin Buck Punkte 67237

Der Grund dafür ist, dass das Gleichheitszeichen in der Computerprogrammierung eher ein Zuweisungsoperator als eine "mathematische Gleichheitsbedingung" ist. Dass die Zeichenkette unveränderlich ist, hat damit nichts zu tun. Es geht darum, dass das Gleichheitszeichen eher ein "Zuweisungsoperator" als eine mathematische Gleichheitsbedingung ist.

Das bedeutet, dass A = B; und B = C; nicht bedeutet, dass A = C;

stattdessen bedeutet es

A wurde so eingestellt, dass er auf den Wert von B verweist, so dass der Wert von B jetzt der Wert von A ist. B wurde so eingestellt, dass er auf den Wert von C verweist, so dass der Wert von C jetzt der Wert von B ist, aber der Wert von A bleibt unverändert.

Wenn Zeichenketten nicht unveränderlich wären

String myString = "Hello";
myString.replace(3, "p"); // replace starting at char #3 (the second 'l')
System.out.println(myString); // would print "Help"

Aber da Strings unveränderlich sind;

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"

4voto

Jon Skeet Punkte 1325502

Die Rolle, die die Aussage in der Erklärung spielt, hängt von der Erklärung selbst ab. Je nach dem Rest der Erklärung kann sie schädlich oder nützlich sein.

Ich persönlich würde diese Aussage erst relativ spät in der Erklärung verwenden (zumindest heutzutage). Die Unveränderlichkeit von Zeichenketten ist einfach nur hinderlich - wie auch bei Erklärungen zur Parameterübergabe. Ich würde mit einer Erklärung beginnen, die eine veränderbare Klasse verwendet, etwa so:

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!

Hier würde ich erklären, dass x y y sind wie Zettel, auf denen die Adressen von Häusern stehen. Die Zuordnung in der zweiten Zeile kopiert keine Haus - er kopiert die Adresse eines Hauses. Die Zuordnung auf der dritte Linie ändert nicht die Farbe der Eingangstür des ersten Hauses - sie schafft eine neu Haus und radiert dann die Adresse auf dem ersten Blatt Papier aus ( x ), und schreibt die neue Adresse auf. Das ändert nichts an dem ersten Haus oder dem zweiten Zettel ( y ).

Ich würde dann ein zweites Beispiel anführen:

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!

Diesmal gibt es nur ein Haus - wenn ich die Tür eines Hauses streiche und du es mit der Adresse besuchst, die ich dir vorher gegeben habe, wirst du sehen, dass die Haustür jetzt rot ist.

So weit, so gut. Jetzt Ich könnte auf das ursprüngliche Beispiel zurückkommen und sagen, dass es bereits wie der erste Hausausschnitt aussieht und nicht wie der zweite, so dass es sich genauso verhält. Ich kann dann sagen, dass die Unveränderlichkeit von Zeichenketten bedeutet, dass man nicht einmal schreiben. Code, der wie das zweite Hausbeispiel aussieht, aber Zeichenketten verwendet. Die Unveränderlichkeit von Strings wäre also nicht sofort für die Erläuterung des bestehenden Codes relevant, aber er wäre trotzdem in derselben Antwort erschienen.

(Ich muss auch darauf hinweisen, dass Referenzen sich zwar wie reale Adressen verhalten, ich aber nicht behaupte, dass sie dasselbe sind wie "Speicheradressen" oder Zeiger. Sie müssen nicht sein . Ich verwende den Begriff in strenger Analogie zur realen Welt, und das ist alles. Das ist ein Nachteil des Beispiels, aber ich glaube nicht, dass es zu viel Schaden anrichtet).

Ich könnte dann auch über Werttypen sprechen und überlegen, was passiert wäre, wenn House ein Wertetyp war - und auch von veränderbaren Wertetypen abgeraten.

Um zu wissen, ob meine Antwort in einer Sprache mit veränderbaren Zeichenketten noch relevant wäre, müssten wir mehr darüber wissen, wie sich Zeichenkettenliterale verhalten. Eine Sprache, die in jeder Hinsicht mit C# identisch wäre andere als die Veränderbarkeit von Zeichenketten wäre eine furchtbare Sprache, wie man schreiben könnte:

// Hypothetical bad language
string x = "dog";
x.MutateTo("cat");
Console.WriteLine("dog"); // Prints cat!

Das wäre natürlich nicht wünschenswert, so dass sich vermutlich das Verhalten von String-Literalen ändern müsste. Sie sprechen auch von möglichen Änderungen der Bedeutung des Zuweisungsoperators usw. Es ist schwierig, konkrete Aussagen über eine hypothetische Sprache zu machen, ohne genau zu wissen, wie sie sich verhält.

3voto

Anthony Pegram Punkte 119149

Die Erklärung ist, dass dieses Beispiel nichts mit Unveränderlichkeit zu tun hat.

Sie haben zwei Variablen, die ursprünglich denselben Wert enthielten, was bei einer Zeichenkette bedeutet, dass sie auf dasselbe Objekt im Speicher verweisen. Dann ändern Sie den Wert einer der Variablen und verweisen sie auf ein anderes Objekt im Speicher.

Das ist nicht anders, als wenn man sagt

int a = 4;
int b = a;
a = 5; 

Oder

string x = "Foo";
string y = x;
x = "Bar";

Oder

Foo foo = new Foo() { Bar = 42 };
Foo otherFoo = foo;
foo = new Foo() { Bar = 17; }

Die Variablen verweisen momentan auf dieselbe Sache. Sie sind ansonsten nicht für alle Zeit untrennbar miteinander verbunden. Sobald man eine auf etwas anderes verweist, endet ihre Gemeinsamkeit.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X