2010-02-09 3 views
16

a)Da Strings unveränderbar sind, zeigen Variablen mit identischen String-Werten auf dasselbe String-Objekt?

 string s = "value"; 
     string s1 = "value"; 

Do s und s1 Referenzvariablen auf gleiche Zeichenfolge Objekt zeigen (Ich gehe davon aus dies auf die Tatsache zurückzuführen, dass Strings unveränderlich sind)?

b) Ich realisiere, dass Gleichheitsoperatoren (==,> etc) neu definiert wurden, um die Werte von String-Objekten zu vergleichen, aber beim Vergleich zweier Strings mit den statischen Methoden Object.Equals() und Object.ReferenceEquals ()

thanx

+2

Ich bin kein Experte, aber überprüfen Sie diesen Link auf String Internment. http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool – ChaosPandion

+10

Siehe auch meinen Artikel dazu für einige zusätzliche Kommentare: http://blogs.msdn.com/ericlippert/archive/2009/09/ 28/string-interning-and-string-empty.aspx –

+0

@Eric - Großartig gelesen, vielen Dank für den Link. – ChaosPandion

Antwort

21

Nein, nicht alle Strings mit dem gleichen Wert sind die gleichen Objektreferenzen.

Vom Compiler generierte Strings werden alle interniert und haben dieselbe Referenz. Zur Laufzeit generierte Strings werden standardmäßig nicht interniert und sind unterschiedliche Referenzen.

var s1 = "abc"; 
var s2 = "abc"; 
var s3 = String.Join("", new[] {"a", "b", "c"}); 
var s4 = string.Intern(s3); 
Console.WriteLine(ReferenceEquals(s1, s2)); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s3)); // Returns False 
Console.WriteLine(s1 == s3); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s4)); // Returns True 

Beachten Sie die Zeile oben, wo Sie eine Zeichenfolge zwingen kann, zu verwenden String.Intern(string) interniert, die dann können Sie Objekt Gleichheit statt Zeichenfolge Gleichheit für einige Kontrollen verwenden, die viel schneller ist. Ein Beispiel, in dem dies sehr häufig verwendet wird, ist innerhalb des generierten XML-Serializer-Codes zusammen mit der Namenstabelle.

+1

+1, um zu verdeutlichen, dass zur Laufzeit erstellte Strings manuell interniert werden müssen. – ChaosPandion

+0

Es könnte sich lohnen, hinzuzufügen var s4 = string.Intern (s3); Console.WriteLine (ReferenceEquals (s1, s4)); // Gibt True zurück – Dolphin

+0

@Dolphin, guter Punkt, ich aktualisierte die Antwort. –

3

Ja, so werden diese auf die gleiche Zeichenfolge verweisen, weil sie beide als Stringliterale definiert sind. Wenn Sie eine Zeichenfolge programmatisch erstellen, müssen Sie die Zeichenfolge manuell internieren.

Dies liegt daran, dass das .NET-Framework die Zeichenfolgenliterale in Ihrem Programm in den internen Pool integriert. Sie können String.Intern verwenden, um diese Referenz abzurufen, oder Ihre eigene runtimegenerierte Zeichenfolge manuell zu internieren.

Weitere Einzelheiten finden Sie in der docs for Intern:

Folglich wird eine Instanz einer Zeichenkette mit einem bestimmten Wert existiert nur einmal im System.

Zum Beispiel, wenn Sie die gleiche Zeichenkette mehreren Variablen zuzuweisen, ruft die Laufzeit die gleiche Verweis auf die Zeichenkette aus dem intern Pool und weist sie jede Variable

+2

Dies ist jedoch durch die Implementierung, nicht die Spezifikation. –

+0

True - aber die Implementierung tut dies derzeit für Literalwerte. –

+0

Ich fügte etwas Klärung in meine Antwort ein. –

2

Mit der aktuellen CLR identisch wörtlichen Zeichenfolgen verweisen auf dieselben tatsächlichen Objekte. Der Prozess wird als Interning bezeichnet und gilt für alle Kompilierungszeit-Strings.

Zur Laufzeit erstellte Zeichenfolgen sind standardmäßig nicht interniert, können jedoch durch Aufruf von string.Intern zur internierten Auflistung hinzugefügt werden.

Eine ausführliche Erläuterung zur Speicherung von .NET-Zeichenfolgen finden Sie unter my answer for this question.

Verwandte Themen