Ich bin auf "CorruptedString" (Lösung) gestoßen . Hier ist folgender Programmcode aus dem Buch:
var s = "Hello";
string.Intern(s);
unsafe
{
fixed (char* c = s)
for (int i = 0; i < s.Length; i++)
c[i] = 'a';
}
Console.WriteLine("Hello"); // Displays: "aaaaa"
Warum zeigt dieses Programm "aaaaa" an? Ich verstehe dieses Programm wie folgt:
- Die CLR reserviert "Hallo" im internen Pool (ich stelle mir den internen Pool als eine Reihe von Zeichenfolgen vor).
string.Intern(s)
tut eigentlich nichts, weil die CLR die Zeichenfolge "Hallo" reserviert hat - sie gibt nur die Adresse der reservierten Zeichenfolge "Hallo" zurück (Objekt s hat dieselbe Adresse)- Das Programm ändert den Inhalt der Zeichenfolge "Hallo" über einen Zeiger
- ??? Die Hello-Zeichenfolge sollte im internen Pool fehlen und ein Fehler sein! Aber es ist in Ordnung; Das Programm wird erfolgreich ausgeführt.
Wie ich den internen Pool verstehe, ist es wie eine Art Wörterbuch von String zu String. Oder habe ich etwas verpasst?
Antworten:
Wenn Sie "Hallo" zum ersten Mal verwenden, wird es in den globalen String-Speicher der Anwendung integriert. Basierend auf der Tatsache, dass Sie im
unsafe
Modus ausführen (mehr dazuunsafe
hier ), erhalten Sie einen direkten Verweis auf Daten, die an den Speicherorten gespeichert sind, die ursprünglich für den Wert der Zeichenfolge zugewiesens
wurdenfor (int i = 0; i < s.Length; i++) c[i] = 'a';
Sie bearbeiten, was sich im Speicher befindet. Wenn es das nächste Mal auf den Speicher für internierte Zeichenfolgen zugreift, wird dieselbe Adresse im Speicher verwendet, die die gerade geänderten Daten enthält. Ohne wäre das nicht möglich
unsafe
.string.Intern(s);
spielt hier keine Rolle; es verhält sich genauso, wenn Sie es auskommentieren.Dann vorbei
Console.WriteLine("Hello"); // Displays: "aaaaa"
.NET
prüft, ob es einen Eintrag für eine Adresse gibt, für die er erhalten wurde,"Hello"
und einen: den, den Sie gerade aktualisiert haben"aaaaa"
. Die Anzahl der'a'
Zeichen wird durch die Länge von bestimmt"Hello"
.quelle
string.Intern(s)
eigentlich nichts in diesem Programm. Sie können diese Zeile kommentieren und das Programm funktioniert genauso (weil "Hallo" reserviert hatte). Aber ich stimme Ihnen zuConsole.WriteLine("Hello");
- "Hallo" ist nur ein Verweis auf bereits bekannte Zeichenfolge.Obwohl die Antwort von @Jaroslav Kadlec korrekt und vollständig ist, möchte ich weitere Informationen zum Verhalten des Codes hinzufügen und erklären, warum dies
string.Intern(s);
in diesem Fall nutzlos ist .Über Intern Pool
Tatsächlich führt .NET die String-Internierung für alle String-Literale automatisch aus. Dazu wird eine spezielle Tabelle verwendet, in der Verweise auf alle eindeutigen Strings in unserer Anwendung gespeichert sind.
Es ist jedoch wichtig zu beachten, dass in der Kompilierungsphase nur explizit deklarierte Zeichenfolgen interniert werden .
Betrachten Sie den folgenden Code:
var first = "Hello"; //Will be interned var second = "World"; //Will be interned var third = first + second; //Will not be interned
Natürlich möchten wir unter bestimmten Umständen einen String zur Laufzeit internieren, und dies kann
String.Intern
nach Überprüfung mit erfolgenString.IsInterned
.Kommen wir also zum Ausschnitt des OP zurück:
//... var s = "Hello"; string.Intern(s); //...
In diesem Fall
string.Intern(s);
ist es nutzlos, da es bereits in der Kompilierungsphase interniert ist.quelle
string.Intern(s)
. Zeichenfolgen können nicht interniert werden (siehe msdn.microsoft.com/en-us/library/… )