8
votes

String interne?

Le deuxième appel de referfeequals renvoie false. Pourquoi la chaîne de S4 n'est-elle pas internée? (Je me fiche des avantages de StringBuilder sur la concaténation de chaînes.)

string s3 = "tom";
string s4 = "to";
s4 += "m";
String.Intern(s4);

Console.WriteLine(s3 == s4); //true
Console.WriteLine(object.ReferenceEquals(s3, s4)); //false
Console.WriteLine(string.IsInterned(s3) != null);  //true (s3 is interned)
Console.WriteLine(string.IsInterned(s4) != null);  //true (s4 is interned)


4 commentaires

S'il vous plaît, vérifiez une fois de plus avec S4 = String.Intern (S4); Console.write (objet.reefervants (S3, S4)); Il revient vrai pour .NET 2.0 ,3,0,3.5,4.0. De plus, si vous testez S3 = String.Intern (S3); Console.write (objet.reeferequives (S3, S1)); Vous pouvez voir que S3 = String.Intern (S3); Ne faites rien parce que tel que correct écrit Scott Dorman, tous de S1 jusqu'à S3 sont déjà interrompers et seulement S4 point sur un pointeur de tas unique avant de le changer avec S4 = String.Intern (S4);


String.Interned () ne signifie pas que l'objet String transmis a été créé comme une chaîne interne, cela signifie qu'il y en a un dans le magasin interné que de la même valeur. Déroutant, hein!


Logique. Mais String.Intern (S4) interne la chaîne alors?


Oui, il fait stagiaire la chaîne mais vous ne comparez toujours pas la référence interne. Regardez la mise à jour de ma réponse pour plus d'informations. De MSDN: La méthode interne utilise le pool interne pour rechercher une chaîne égale à la valeur de Str. Si une telle chaîne existe, sa référence dans la piscine interne est renvoyée. Si la chaîne n'existe pas, une référence à STR est ajoutée à la pool interne, puis cette référence est renvoyée.


6 Réponses :


3
votes

Les chaînes sont immuables. Cela signifie que leur contenu ne peut pas être changé.

Lorsque vous faites s4 + = "m"; en interne, le CLR copie la chaîne à un autre emplacement en mémoire contenant la chaîne d'origine et la partie annexée.

voir Référence de chaîne MSDN .


3 commentaires

Je crois comprendre que les chaînes sont immuables. Mais tout le point de projection est de sauver la mémoire juste? Pourquoi le CLR ne peut-il pas dire, hé, j'ai la même valeur dans ma piscine interne, je vais juste le pointer.


@Rkrierteur: Il est assez coûteux de vérifier toutes les chaînes de la pool interne, que l'une d'entre elles soit égale au résultat de l'opération - après chacune des opérations! Donc, le CLR sacrifie l'efficacité de la mémoire à la vitesse d'exécution. Le calcul de la chaîne au moment de la compilation peut être lent, de sorte que ses résultats peuvent être internés. Les calculs au moment de l'exécution doivent être rapides, ce qui vérifie chaque résultat contre une série d'autres cordes semble être irréalisable.


Alors la chaîne interne est principalement faite au moment de la compilation? Je viens de remarquer que quand je fais string.Intern (S4);, je suis toujours faux. S'il vous plaît, expliquez.



17
votes

la chaîne dans S4 est internétique. Cependant, lorsque vous exécutez S4 + = "m"; , vous avez créé une nouvelle chaîne qui ne sera pas internée car sa valeur n'est pas un littéral à chaîne mais le résultat d'une opération de concaténation à chaîne. En conséquence, S3 et S4 sont deux instances de chaîne différentes dans deux emplacements de mémoire différents.

Pour plus d'informations sur la chaîne interne, regardez ici , spécifiquement au dernier exemple. Lorsque vous faites String.Intern (S4) , vous interrogeez la chaîne, mais vous n'effectuez toujours pas un test d'égalité de référence entre ces deux chaînes internes. La méthode string.Intern_interner renvoie la chaîne interne, de sorte que vous auriez besoin de le faire: xxx


2 commentaires

Marqué comme réponse merci. Des choses encore étranges. Je le dis à stagiaire S4 et cela renvoie une référence à une chaîne déjà internée dans la piscine. Alors que la pauvre S4 est tout simplement suspendue comme une chaîne non internée dans le tas.


Merci. Il renvoie une référence, mais si la valeur de chaîne est passée à mesure que l'argument n'est pas déjà interné, elle sera internée, puis la référence est renvoyée. String Interning est en réalité une technique d'optimisation principalement utilisée par le compilateur afin de réduire le nombre d'instances de chaîne à travers l'application. Sauf si vous créez beaucoup de chaîne, vous ne verrez probablement pas beaucoup d'avantage à le faire vous-même.



1
votes

en C #, chaque chaîne est un objet distinct et ne peut pas être édité. Vous créez des références à eux, mais chaque chaîne est distincte. Le comportement est cohérent et facile à comprendre.

Pourrais-je suggérer d'examiner la classe StringBuilder pour manipuler des chaînes sans créer de nouvelles instances? Cela devrait être suffisant pour tout ce que vous voulez faire avec des chaînes.


1 commentaires

Utilisez uniquement un StringBuilder si vous avez besoin de concatez de grandes chaînes ensemble. Dans tous les autres cas, le temps sauvé est si minimal que cela n'a pas d'importance. De plus, les chaînes sont placées dans une matrice de chaînes déjà créées en interne, cela signifie que si vous créez la chaîne "bonjour", toute chaîne supplémentaire "Hello" pointera sur la même référence en mémoire.



2
votes

Tout d'abord, tout écrit jusqu'à présent sur les chaînes immuables est correcte. Mais il y a des choses importantes qui ne sont pas écrites. Le code xxx

affiche vraiment "vrai", mais uniquement à cause d'une petite optimisation du compilateur ou d'une petite optimisation de compilateur, car CLR ignore C # Compiler Attributs (voir "CLR via C #" Livre) et placer une seule chaîne "tom" dans le tas.

second, vous pouvez réparer la situation avec les lignes suivantes: xxx

fonction String.Intern calcule un code de hachage de la chaîne et recherchez le même hachage dans la table de hachage interne. Parce que cela trouvera ceci, il retourne la référence à l'objet de chaîne déjà existant. Si la chaîne n'existe pas dans la table de hachage interne, une copie de la chaîne est faite et le hachage calculé. Le collecteur des ordures ne libère pas de mémoire pour la chaîne, car elle est référencée par la table de hachage.


0 commentaires

2
votes

Source: HTTPS: //blogs.msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-String-empty/

String Interning est une technique d'optimisation par le compilateur. Si vous avez deux littéraux de chaîne identiques dans une unité de compilation, le code généré garantit qu'il n'y a qu'un seul objet de chaîne créé pour toute l'instance de ce littéral (caractères enfermé dans des guillemets doubles) dans l'ensemble.

i Je suis du fond C #, je peux donc expliquer en donnant un exemple à partir de celui-ci: xxx

sortie des comparaisons suivantes: xxx < p> note1 : les objets sont comparés par référence.

NOTE2 : typeof (int) .name est évalué par méthode de réflexion afin qu'il ne soit pas évalué au moment de la compilation. Voici ces comparaisons sont faites à l'heure de la compilation.

Analyse des résultats: 1) True parce qu'ils contiennent les deux mêmes littéraux et que le code généré n'aura qu'un seul objet référençant "int32". voir la note 1 .

2) true car le contenu de la valeur est vérifié qui est identique.

3) faux parce que str2 et obj ne le fait pas avoir le même littéral. Voir Note 2 .


0 commentaires

0
votes

Lors de la comparaison de deux objets, pas de chaînes, l'opérateur d'égalité de chaîne n'est pas appelé car il est une méthode statique sans polymorphisme.

Voici un test: p>

object arr   o1  == o2  ? False
string arr   o3  == o4  ? True
object const o5  == o6  ? True
string const o7  == o8  ? True
object cnsl  o9  == o10 ? False
string cnsl  o11 == o12 ? True
o1.Equals(o2) ? True
o3.Equals(o4) ? True
o5.Equals(o6) ? True
o7.Equals(o8) ? True
o9.Equals(o10) ? True
o11.Equals(o12) ? True


1 commentaires

@Codecaster Ok, merci de m'aider à m'améliorer.