Je suis tombé sur “CorruptedSsortingng” (Solution) . Voici le code du programme suivant du livre:
var s = "Hello"; ssortingng.Intern(s); unsafe { fixed (char* c = s) for (int i = 0; i < s.Length; i++) c[i] = 'a'; } Console.WriteLine("Hello"); // Displays: "aaaaa"
Pourquoi ce programme affiche “aaaaa”? Je comprends ce programme comme suit:
ssortingng.Intern(s)
ne fait en réalité rien, car le CLR avait réservé la chaîne “Hello” – il ne fait que renvoyer l’adresse de la chaîne “Hello” réservée (l’object a la même adresse) Comme je comprends le pool interne, c’est comme une sorte de dictionnaire de chaîne à chaîne. Ou peut-être que j’ai raté quelque chose?
Lorsque vous utilisez “Hello” pour la première fois, il est interné dans le magasin global de chaînes de l’application. Basé sur le fait que vous exécutez en mode unsafe
(plus unsafe
ici ), vous obtenez une référence directe aux données stockées dans les emplacements alloués à l’origine pour la valeur de chaîne s
, donc par
for (int i = 0; i < s.Length; i++) c[i] = 'a';
vous modifiez ce qui est en mémoire. Lorsqu'il accédera au magasin de chaînes internes la prochaine fois, il utilisera la même adresse en mémoire, contenant les données que vous venez de modifier. Cela ne serait pas possible sans unsafe
. ssortingng.Intern(s);
ne joue pas de rôle ici; il se comporte de la même manière si vous le commentez.
Puis par
Console.WriteLine("Hello"); // Displays: "aaaaa"
.NET
vérifie s'il y a une entrée pour une adresse obtenue pour "Hello"
et il y a: celle que vous venez de mettre à jour pour être "aaaaa"
. Le nombre de caractères 'a'
est déterminé par la longueur de "Hello"
.
Bien que la réponse de @Jaroslav Kadlec soit correcte et complète, je voudrais append quelques informations supplémentaires sur le comportement du code et pourquoi ssortingng.Intern(s);
est inutile dans ce cas .
En fait, .NET exécute automatiquement l’internalisation de chaînes pour tous les littéraux de chaîne, en utilisant une table spéciale qui stocke les références à toutes les chaînes uniques de notre application.
Cependant, il est important de noter que seules les chaînes explicitement déclarées sont internées sur la compilation .
Considérez le code suivant:
var first = "Hello"; //Will be interned var second = "World"; //Will be interned var third = first + second; //Will not be interned
Bien sûr, dans certaines circonstances, nous aimerions interner une chaîne au moment de l’exécution et cela peut être fait par Ssortingng.Intern
après avoir vérifié avec Ssortingng.IsInterned
.
Revenons donc à l’extrait de l’OP:
//... var s = "Hello"; ssortingng.Intern(s); //...
Dans ce cas, ssortingng.Intern(s);
est inutile car il est déjà interné à la compilation.