| 

.NET C# Java Javascript Exception

6
Ich will in einem String einen Text (sagen wir ABC) ersetzen durch einen anderen Text (sagen wir XYZ). Rufe ich die Replace-Methode auf, passiert aber nichts – der String ist immer noch der gleiche wie vorher. Was mache ich falsch? Oder ist das ein Bug in .NET?
News:
03.06.2011
Mondschatten 61 1 3
4 Antworten
4
Nein, das ist kein Bug sondern ein Feature. Strings sind immutable, also unveränderlich. Die Replace-Methode ändert nicht den String, auf dem Du sie aufrufst, sondern erzeugt einen neuen, in dem die gewünschte Änderung enthalten ist. Wenn Du mit dem neuen String weiterarbeiten willst, mußt Du ihn Deiner Variablen erneut zuweisen.

string s = "ABCDEF";
s = s.Replace("ABC", "XYZ");
03.06.2011
Matthias Hlawatsch 13,2k 4 9
zum Thema Strings sind unveränderlich (Bug oder Feature:) typeof(string).GetField("Empty").SetValue(null, "HaHa");
Mario Priebe 03.06.2011
Strings sind trotzdem unveränderlich:
string s1 = string.Empty;
typeof(string).GetField("Empty").SetValue(null, "HaHa");
string s2 = string.Empty;
bool b = object.ReferenceEquals(s1, s2); // false, bei mutable müsste true sein

Dass der Wert, wenn er auch readonly ist, per Reflektion geändert werden ist eben die Gefahr von Reflektion.
gfoidl 03.06.2011
Marios Beispiel geht ins Leere, weil Empty ein *statisches* Feld der Klasse String ist (vom Typ String). Wenn das geändert wird, ändert sich keine Instanz von String.
Matthias Hlawatsch 03.06.2011
Das Beispiel passt in dieser Hinsicht schon. Das statische Feld hält ein Objekt der String-Klasse mit dem Wert "". Wäre der String mutable passt es sogar ganz, aber der String ist eben nicht mutable - wie ich oben zeigte ;-)

Eine Instanz von String ändert sich - wegen immutable - sowieso nie.

Mit statischem Feld das gar nix zu tun ;-)
gfoidl 03.06.2011
Ich finde, schon, dass es wesentlich ist, dass "Empty" ein statisches Feld ist. Eine Klasse gilt als immutable, wenn man Instanzen der Klasse nach ihrer Erzeugung nicht mehr ändern kann. Marios Beispiel habe ich so verstanden, dass er zeigen wollte, dass sich das Empty-Feld der String-Klasse ändern läßt. Das gehört aber keiner Instanz von String, somit ändert er damit auch keinen String. Er weist nur einer Art globalen Variablen, die zufällig in der String-Klasse eingebaut ist, einen neuen String zu.
[Fortsetzung folgt]
Matthias Hlawatsch 04.06.2011
Bei einem hypothetischen nicht-statischen Feld von String würde hingegen
typeof(string).GetField("SomeField").SetValue(someString, "HaHa");
die Instanz someString ändern.
Matthias Hlawatsch 04.06.2011
"Empty" ist eine Instanz einer String-Klasse die Mario ändern probiert hat. Und das hat nicht geklappt, da diese nicht änderbar ist. Daher wurde eine neue Instanz der String-Klasse erstellt mit dem Wert "HaHa" und diese dem statischen Feld Empty der String-Klasse zugewiesen.
Dass die Instanz der String-Klasse mit dem Wert "Empty" (ursprünglich) ein statisches Feld in der String-Klasse ist hat mE damit nix zu tun.
gfoidl 04.06.2011
3
Der String selber wird nicht verändert. Die Methode selber gibt den veränderten String zurück.

//Keine Veränderung am Original
string original = "ABC";
string veraendert = original.Replace("ABC", "XYZ");

Console.WriteLine(original);
Console.WriteLine(veraendert);

//Oder - Ergebnis zuweisen
original = original.Replace("ABC", "XYZ");


D.h. im Beispiel:
Auch durch Aufruf der Methode .Replace() wird der String 'original' nicht verändert. Es wird nur ein String zurückgegeben und diesen kannst du dann speichern. Natürlich kannst du den veränderten String dann wieder zuweisen.
03.06.2011
michel 71 1
3
Aus den bereits genannten Gründen verwende ich gerne den Stringbuilder. Dieser ist mutable und es können Veränderungen vorgenommen werden:
StringBuilder sb = new StringBuilder("ABCDEF");
sb.Replace("ABC", "XYZ");
sb.Replace("Y", "MoreText");
Console.WriteLine(sb.ToString());

StringBuilder Class
Represents a mutable string of characters.
03.06.2011
Martin Fuchs 1,4k 9
1
Hat dafür aber den Nachteil das die Replace-Methode keine Optionen, z.B. für Caseinsesitiv, entgegen nimmt.
Floyd 03.06.2011
2
Ich würde gerne mal sehen, wie Du das machst. Aber ich vermute, Du erwartest, dass der Originalstring verändert wird. Hast Du es mal so probiert:

string theString = "abcdefg";
string result = theString.Replace("abc" "z");


In result befindet sich jetzt "zdefg". Die originale Zeichenkette wird nie verändert, wiel strings in .NET unveränderlich sind.
03.06.2011
Andreas Ganzer 1,4k 1 8
zum Thema Strings sind unveränderlich (Bug oder Feature:) typeof(string).GetField("Empty").SetValue(null, "HaHa");
Mario Priebe 03.06.2011
Strings sind trotzdem unveränderlich:
string s1 = string.Empty;
typeof(string).GetField("Empty").SetValue(null, "HaHa");
string s2 = string.Empty;
bool b = object.ReferenceEquals(s1, s2); // false, bei mutable müsste true sein

Dass der Wert, wenn er auch readonly ist, per Reflektion geändert werden ist eben die Gefahr von Reflektion.
gfoidl 03.06.2011

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH