2016-08-05 2 views
-6

Je sais que les chaînes sont inmutables, une fois créées nous ne pouvons pas les changer, j'ai lu que si nous créons un nouvel objet chaîne et lui assignons une valeur, nous assignons une autre valeur au même objet chaîne en interne objet créé et affecté avec la nouvelle valeur. Disons que j'ai:Comment fonctionne la chaîne dans C#?

string str = "dog";    
str = "cat"; 

Si j'écris Console.WriteLine(str); retourne cat. Donc, intérieurement, il y a deux objets? Mais ils ont le même nom? Comment ça fonctionne? J'ai fait quelques recherches sur google mais je n'ai pas encore trouvé quelque chose de suffisamment convaincant pour que je puisse clarifier mes pensées à ce sujet. Je sais que les chaînes sont des types de référence, donc nous avons un objet dans la pile avec une référence à une valeur dans le tas, que se passe-t-il dans ce cas? (Voir le code ci-dessus).

J'ai téléchargé une photo, excusez-moi si je me trompe sur l'idée de la pile et le tas c'est pourquoi je pose cette question. L'image reflète-t-elle ce qui se passe dans la première ligne de code (string str = "dog";)? Et alors que devrait-il se passer dans la deuxième ligne du code ?? La valeur dog dans les changements de tas? Et puis un nouvel objet dans la pile est créé en le référençant? Alors qu'arrive-t-il avec l'objet qui était là avant? Ont-ils le même nom? Je suis désolé pour autant de questions mais je pense qu'il est très important de comprendre cela correctement et de savoir ce qui se passe dans les coulisses ... enter image description here

Répondre

2

examiner String Interning ou .Net String Intern table ou CLR Intern Pool.Fondamentalement, Common Language Runtime (CLR) gère une table de valeurs de chaîne [unique], et chaque fois que vous manipulez une chaîne dans votre code, le CLR examine cette table interne pour voir si la nouvelle valeur que vous essayez de créer est déjà là ou pas. Si c'est le cas, il suffit de réaffecter la variable que vous modifiez pour qu'elle pointe vers cette entrée dans le pool interne. Sinon, il ajoute la valeur au pool et renvoie cette nouvelle référence. Les anciennes valeurs du pool, qui ne sont plus référencées par les variables, récupèrent les ordures.

+0

très difficile pour moi de choisir une réponse parce que toutes vos réponses ont été très descriptives, je suis clarifié maintenant à ce sujet, merci !!! – AlexGH

1

Oui, il y a deux objets. Non, ils n'ont pas le même nom. Essayez de ne pas considérer une variable comme un "nom" pour l'objet lui-même en soi - c'est plutôt un nom temporaire pour l'emplacement de l'objet en mémoire. (La raison pour laquelle il est quelque peu trompeur de considérer une variable comme un "nom" pour l'objet est que vous pouvez avoir plusieurs variables se référant au même objet, ce n'est pas le cas de plusieurs "noms" il y a plusieurs objets - c'est comme ça que vous rangez la référence). "Chaîne str" a d'abord une référence à la chaîne "chien"

Après avoir assigné "cat" à "str", la variable a maintenant une référence à la chaîne "cat".

Les deux chaînes existent toujours en mémoire (au moins temporairement), mais la chaîne "dog" n'est plus accessible car vous n'y avez pas de référence (et donc plus de "connaître" son emplacement). Vous ne savez pas à l'avance combien de temps ils existeront tous les deux dans la mémoire bien que le garbage collector puisse supprimer la chaîne "dog" de la mémoire à tout moment car il n'y a plus aucune référence à elle.

Vous avez raison concernant la valeur sur la pile avec la référence à l'objet sur le tas d'ailleurs - c'est une bonne distinction.

2

Vous êtes proche. Votre image représente exactement ce qui se passe dans la première ligne de code. Cependant, les choses sont un peu différentes de ce que vous décrivez pour la deuxième ligne de code.

Pour la ligne str = "cat";, un deuxième objet chaîne est créé dans le tas et la variable str est modifiée pour faire référence à ce nouvel objet. Il vous reste str pointant vers "cat" et un objet orphelin "dog" sur le tas sans référence à celui-ci.

L'objet "dog" peut être nettoyé par le garbage collector car il n'y a aucune référence.

4

Lorsque vous attribuez str à "dog", cela se passe comme décrit ci-dessus en mémoire: la variable de référence str est maintenant "pointant vers" l'emplacement de la chaîne que vous venez d'instancier.

str => MEMORY LOCATION "1": "dog" 
     MEMORY LOCATION "2": 
     MEMORY LOCATION "3": 

Lorsque str est réaffecté à votre nouvelle chaîne, « chat », il est aussi créé en mémoire, et maintenant str est ajusté afin qu'il pointe à « chat » dans le nouvel emplacement.

 MEMORY LOCATION "1": "dog" 
str => MEMORY LOCATION "2": "cat" 
     MEMORY LOCATION "3": 

Qu'est-ce qui arrive à "chien"? C'est effectivement inaccessible maintenant, puisque nous n'avons plus de référence à sa localisation (dans la mémoire, tas, les termes sont interchangeables dans cette situation). Plus tard, quand le collecteur de déchets examinera la mémoire pour le nettoyer, il se rendra compte qu'il n'y a rien référençant "chien" et il marquera la mémoire pour être supprimé et remplacé au besoin.