5 votes

Incompréhension de String immuable ou une erreur dans la documentation ?

Je viens de voir cela dans la documentation de MS Visual Studio et la partie en gras ne me semble pas logique. Est-ce incorrect ou est-ce que je ne comprends pas correctement? Si vous exécutez ceci, b semble contenir "hello" (comme je m'y attendrais) et non "h".

Les chaines de caractères sont immuables - le contenu d'un objet de chaîne de caractères ne peut pas être modifié après la création de l'objet, bien que la syntaxe donne l'impression que vous pouvez le faire. Par exemple, lorsque vous écrivez ce code, le compilateur crée en réalité un nouvel objet de chaîne de caractères pour contenir la nouvelle séquence de caractères, et la variable b continue de contenir "h".

string b = "h";

b += "ello";

7voto

user7116 Points 39829

Vous avez effectué une addition ET un assignement en une seule étape. Les chaînes de caractères sont immuables, mais aussi un type de référence.

string b = "h";
b = b + "ello";

Nous pouvons visualiser la pseudo-mémoire de cette manière :

string b = "h";         // b    := 0x00001000 ["h"]
string tmp1 = "ello";   // tmp1 := 0x00002000 ["ello"]
string tmp2 = b + tmp1; // tmp2 := 0x00003000 ["hello"]
string b = tmp2;        // b    := 0x00003000 ["hello"]

Je ne suis pas totalement sûr d'où vous tirez ce texte, car en lisant la documentation de la classe string, je trouve (bien que je ne pense pas que "h" soit réellement éliminé par le garbage collector) :

Les chaînes de caractères sont immuables - le contenu d'un objet string ne peut pas être modifié après la création de l'objet, bien que la syntaxe donne l'impression que c'est possible. Par exemple, lorsque vous écrivez ce code, le compilateur crée en fait un nouvel objet string pour contenir la nouvelle séquence de caractères, et cet nouvel objet est assigné à b. La chaîne "h" est ensuite éligible à la récupération par le garbage collector.

@Jon Skeet soulève le fait que "h" ne sera jamais éliminé par le garbage collector en raison de l'interning des chaînes, et je suis d'accord avec lui, mais le standard C# est encore plus en accord avec lui, sinon la déclaration suivante de la section §2.4.4.5 Litéraux de chaînes ne serait pas vraie :

Chaque litéral de chaîne ne résulte pas nécessairement en une nouvelle instance de chaîne. Lorsque deux litéraux de chaîne ou plus équivalents selon l'opérateur d'égalité de chaînes (§7.9.7) apparaissent dans le même programme, ces litéraux de chaîne font référence à la même instance de chaîne.

5voto

Dave Costa Points 25282

Les gens semblent ne pas comprendre la question. Personne ne conteste le fait que les objets chaîne ne sont pas immuables. Le point de discorde est ce qu'il a souligné:

et que la variable b continue de contenir "h"

Je suis d'accord avec l'OP que cette partie du document est incorrecte sur deux points:

(1) Dans le sens intuitif évident que si vous affichez(b) (ou tout autre déclaration correcte dans ce langage) après ses deux lignes d'exemple, vous obtiendrez "hello" comme résultat.
(2) Dans le sens strict où la variable b ne contient pas "h", "hello", ou une quelconque valeur de chaîne. Elle contient une référence à un objet chaîne.

Le contenu de la variable b change en résultat de l'assignation -- il change d'un pointeur vers l'objet chaîne "h" à un pointeur vers l'objet chaîne "hello".

Quand ils disent "contenir" ils veulent vraiment dire "pointer vers". Et ils ont tort, après l'assignation b ne pointe plus vers "h".

Je pense que l'exemple qu'ils voulaient vraiment donner est le suivant:

string a = "h";
string b = a;
b += "ello";

Le point étant que a, je crois, pointerait toujours vers "h"; c'est-à-dire, l'assignation à b ne modifie pas l'objet vers lequel il pointait, mais crée un nouvel objet et modifie b pour pointer vers celui-ci.

(Je n'écris pas vraiment en C# mais c'est ma compréhension.)

4voto

Jon Skeet Points 692016

Oui, les documents sont incorrects. (Les documents pour un certain nombre de méthodes de chaîne impliquent également la mutabilité. Ils sont essentiellement mal écrits.)

Même l'utilisation de "le compilateur" créant le nouvel objet de chaîne est incorrecte. Fondamentalement, cela fait :

chaîne b = "h";
b = string.Concat(b, "ello");

À ce stade, le travail du compilateur est terminé - c'est le framework qui crée le nouvel objet de chaîne.

4voto

hwiechers Points 4717

La documentation est fausse. La variable b contient maintenant "hello". La chaîne de caractères est immuable mais la variable peut être réaffectée.

4voto

Sam Points 9445

La confusion ici concerne les types de références:
String est un type de référence, pas un type de valeur. Cela signifie que votre variable b n'est pas un objet de type chaîne de caractères, c'est une référence à un objet de type chaîne de caractères en mémoire.
Ce que le document dit, c'est que l'objet en mémoire est immuable.
Cependant, votre référence à l'objet peut être modifiée pour pointer vers un autre objet (immuable) en mémoire.
Pour vous, il pourrait sembler que le contenu de l'objet a changé, mais en mémoire, rien n'a changé et c'est tout ce que signifie ce concept d'immutable.

La chaîne de caractères elle-même est immutable. Ce que votre exemple a modifié n'est pas la classe de chaîne de caractères en mémoire, mais la référence vers laquelle pointe votre variable.

Regardez ce code légèrement modifié:

string b = "h";
string m1 = b;
b += "ello";
// maintenant b == "hello", m1 == "h"

À la fin, b pointera vers "hello", tandis que m1 pointera vers "h". Pour vous, il pourrait sembler que "h" a été changé en "hello", mais ce n'est pas le cas. b+="ello" a créé une nouvelle classe de chaîne de caractères contenant "hello" et l'a assignée à b, tandis que l'ancien b est toujours présent en mémoire et contient toujours "b".

Si la chaîne de caractères n'était pas immutable, m1 contiendrait "hello" aussi, au lieu de simplement "b", car b et m1 pointeraient vers la même référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X