2009-07-27 27 views
2

Ich habe eine Klasse mit 3 String-Eigenschaften. Ich möchte diese in einer Liste speichern, so dass, wenn ich Änderungen an den Strings der Liste mache, sie auch in der Klasse aktualisiert werden.Speichern Sie einen Verweis auf eine Zeichenfolge

Das wäre leicht zu tun, wenn ich Klassenobjekt verwendet, aber String scheint sich anders zu verhalten. Es scheint eine Kopie des Objekts für die Liste zu erstellen, anstatt einen Zeiger auf das Objekt zu haben. Wie soll ich das machen C#? Wenn das nicht möglich ist, gibt es einen besseren Weg?

Antwort

6

Das Problem mit string s ist, dass sie unveränderlich sind. Mit anderen Worten, Sie können nie eine string ändern, sobald es erstellt wird.

Wenn Sie also eine string "ändern" möchten, müssen Sie das Original aus der List entfernen und das Ergebnis in der Liste speichern. Beispiel:

string a = "abcdefg"; 
List<String> list = new List<String>(); 
list.add(a); 

a = a.Substring(0, 5); 

Dieser Code tut nichts, weil die stringa zeigt auf ändert sich nie. Es zeigt nur auf eine neue string.

3

In .NET sind Zeichenfolgen unveränderlich. Wenn Sie die Zeichenfolge ändern, erstellen Sie tatsächlich eine neue und ändern die Referenz.

Ich würde in Betracht ziehen, ein StringBuilder Objekt zu verwenden, um Ihr Problem anzugehen.

+0

+1. StringBuilder tut bereits, was Sie wollen, erstellen Sie keine neue Klasse, es sei denn, die vorhandene Klasse funktioniert nicht. –

+0

StringBuilder wird funktionieren, ist aber eine schlechte Wahl aus dem POV der Leistung. Die einzige Möglichkeit, den Wert einer Instanz zu ändern, besteht darin, sie zu löschen und die neue Zeichenfolge anzuhängen, bei der tatsächlich alle diese Bytes kopiert werden. Und wenn Sie sich die Interna ansehen, sehen Sie, dass es beim ersten Aufruf von ToString eine zweite Kopie erstellt. Da das Ändern mehr als das Zurücksetzen eines Zeigers erfordert, kann es auch nicht atomar sein, so dass es möglicherweise Probleme mit der Thread-Sicherheit gibt. –

+0

@Steven, bitte besorgen Sie sich einige Beweise für diese Behauptung. Meine StringBuilder-Tests zeigen nur die geänderten/ersetzten/angehängten Bytes, die sich ändern, nicht "all diese Bytes". Sehr wenige String-Manipulationen beinhalten lediglich das "Ändern eines Zeigers"; Keine der anderen vorgeschlagenen veränderbaren String-Klassen tun dies, noch sind sie atomar. Alle anderen Vorschläge beinhalten das Erstellen einer neuen Zeichenfolge. –

0

Sie suchen nach einer veränderbaren Saite. Es gibt viele Möglichkeiten, eine Klasse zu erstellen, die sich so verhält, wie Sie es wollen.

Der einfachste Weg wäre, ein StringBuilder-Objekt anstelle einer Zeichenfolge zu verwenden. Sie müssen nur darauf achten, keine neuen StringBuilder-Objekte zu erstellen, sondern das vorhandene zu ändern. Je nachdem, was Sie benötigen, ist dies möglicherweise nicht die beste Option.

Alternativ können Sie Ihre eigene Wrapper-Klasse für String erstellen, die Sie frei manipulieren können. Der Nachteil ist, dass Sie möglicherweise viele Stub-Methoden schreiben müssen, die auf die innere Zeichenkette zurückgreifen, je nachdem, wie Sie sie verwenden möchten. Es wäre einfacher, eine Lese-/Schreib-String-Eigenschaft bloßzustellen. Dies hat den Vorteil, dass Sie genau definieren können, welche Verhaltensweisen Sie wollen, aber das Schreiben wird von vornherein länger dauern. Auch hier müssen Sie sicherstellen, dass Sie keine neuen Instanzen der Wrapper-Klasse erstellen, sondern nur die interne Zeichenfolge der Klasse ändern.

0

Wickeln Sie Ihre Zeichenfolge in eine benutzerdefinierte Klasse, damit Sie sie unter verschiedenen Standorten teilen können. Sie können stattdessen auch Char-Arrays speichern.

+0

Ich würde denken, dass, wenn alles, was Sie brauchen, ein Maß an Indirection ist, eine benutzerdefinierte Klasse ist Overkill. –

2

Da Strings unveränderlich sind, besteht die einfachste Möglichkeit darin, den Verweis auf ein String-Array mit einem Element zu speichern. Das Ersetzen dieses Elements wird dann von jedem bemerkt, der sich auf das Array bezieht.

2

Zeichenfolgen in C# sind unveränderlich, daher können Sie in C# keine Zeichenfolge ändern. Sie können nur neue Zeichenfolgen erstellen.

Sie könnten eher eine Klasse speichern, die ein Zeichenfolge Mitglied

class StringHolder { 
    public StringHolder(string s) { str = s;} 
    public string str; 
} 
... 
List<StringHolder> l1 = new List<StringHolder>(); 
List<StringHolder> l2 = new List<StringHolder>(); 
List<StringHolder> l3 = new List<StringHolder>(); 

StringHolder h = new StringHolder("Test\n"); 
l1.add(h); 
l2.add(h); 
l3.add(h); 

h.str = h.str.Replace("\n",""); 

nun alle Listen beziehen sich auf die gleichen Saiten hat und natürlich die gleiche Zeichenfolge sehen.

Eine weitere Option ist das Speichern von StringBuilder-Objekten in Ihren Listen anstelle von String.

3

Strings sind unveränderlich. Sie können eine Referenz ändern, um auf eine andere Zeichenfolge zu verweisen, aber Sie können eine Zeichenfolge nicht so ändern, dass auch andere Referenzen darauf Wert ändern (außer durch unsicheren, völlig gefährlichen reflektierenden Code) durch Verwendung einer veränderbaren Alternative (z. B. eines StringBuilders) oder durch explizite Indirektion. Ich werde Sie letztere zeigen:

public class Props 
{ 
    private readonly string[] data = new string[2]; 

    public string Foo { 
     get { return data[0]; } 
    } 

    public string Bar { 
     get { return data[1]; } 
    } 

    public IList<string> ModifyValueButNoInsertsList { get { return data;} } 
} 

Wirklich sollten Sie erwägen, eigentlich Zeichenfolge mit [] statt IList in dieser Situation, wie sie es klar Einsätze macht verboten sind, nur Veränderungen der Werte. Da string [] implementiert IList<string> dies ist unwahrscheinlich, dass ein Problem

2
class StringHolder 
{ 
    public string Value { get; set; } 
} 

Halten Sie eine Liste derjenigen, anstatt nur Strings zu sein. Dann können Sie die Value -Eigenschaft abrufen/setzen, um den Zeichenfolgenwert zu aktualisieren.

0

Als eine Randnotiz (wie mehrere erwähnt haben), wenn Sie einige schwere Verarbeitung mit Zeichenfolgen, verwenden Sie die StringBuilder-Klasse. Wegen der unveränderlichen Natur von Strings, Ändern/Verkettung von ihnen in Schleifen oder was hast du - wird viel Aufwand verursachen.

StringBuilder ist dein Freund.

Verwandte Themen