La différence entre les types de référence et les types de valeur est souvent déroutante pour les débutants due à la ne pas comprendre quelle variable de type de valeur contient réellement. Nous savons que: p>
est-il possible d'inspecter chaque type de variable pour voir la valeur ou la référence Je pense que cela aiderait les nouveaux arrivants à comprendre et être très intéressant à explorer. p>
4 Réponses :
Vous pouvez le faire avec un objet épinglé assez facilement;
Cela ne fonctionnera pas pour Types non blittables , comme presque tous Des classes.
Je me suis trompé. On dirait que la seule fois où j'ai besoin de c'était avec des primitives.
Vous pouvez le faire avec dangereux code> code:
Cela fait une copie épinglée de S, alors vous pourquoi ne pas piquer directement?
Nous n'utiliserons pas s code> pour quoi que ce soit.
@Eugenrieck Avez-vous une source pour cette déclaration? Je ne vois pas de copier ici.
Ceci est probablement un pour Jon Skeet, mais j'aurais peut-être un angle différent sur celui-ci: P>
ne vous inquiétez pas strong> trop sur comment em> ces choses sont représentées en mémoire. Sauf si vous avez lu toute la spécification de la langue - qui fait de toute façon? - Vous n'avez pas vraiment besoin de savoir. Vraiment. Ne vous inquiétez pas de mémoriser quelles données sont stockées où sont des chances que c'est la mise en œuvre spécifique. P>
Au lieu de cela, pensez en termes de sémantique, par exemple qu'un type de valeur transmis à une fonction est copié em>, tandis qu'un type de référence est référencé em>. Trucs comme ça. P>
Vous ne voulez pas vraiment savoir quelle est la déclaration d'un type. Crois-moi. Ce que vous voulez savoir, c'est
+1 Voici où Eric Lippert dit la même chose. Les adresses sont un détail de mise en œuvre, la spécification de langue ne mentionne pas les adresses lors de la spécification des références. Découvrez comment ils se comportent et non comme ils fonctionnent.
Pendant que je suis d'accord avec votre déclaration, je ne pense pas que c'est tout au but de la question. Je pense qu'il aimerait savoir comment faire - pas vos opinions sur la raison pour laquelle ce n'est pas important. En appuyant sur la manière dont les fonctionnalités complexes fonctionnent peuvent vous faire un meilleur ingénieur, même si vous ne trouvez pas une utilisation instantanée pour cette connaissance.
Alors que je remercie et que je suis d'accord avec votre réponse, cela ne traite pas du point de ma question. Je voudrais simplement accéder à l'adresse juste pour prouver qu'il est là b> aucune autre raison. Je suis d'accord avec @ adamg.carsensen.
@ Adamg.carsensen - Je suis d'accord avec vous deux: je n'ai pas vraiment répondu à votre question. Mais vous mentionnez «aider les nouveaux arrivants à comprendre» comme une raison et je pense que cela n'aide pas vraiment les nouveaux arrivants beaucoup. Mais il serait intéressant de le considérer d'une perspective de mise en œuvre VM.
est-il possible d'inspecter chaque type de variable pour voir la valeur ou la référence réelle elle-même? p> blockQuote>
juste pour clarifier, la valeur de A em> variable de type de référence em>
est forte> une référence. La référence est la valeur. P> Une référence est une sorte de valeur, comme un Int est une sorte de valeur. Contrairement à un Int, une référence est une valeur qui ne peut être que copiée em> et déréférencée em>; Vous ne pouvez pas observer sa valeur directement dans C #, car sa valeur est un détail de mise en œuvre du collecteur des ordures. p>
est la référence stockée comme une sorte de valeur codée? p> blockQuote>
Oui, exactement. En pratique, une référence est un entier 32 ou 64 bits (selon que vous êtes dans un processus de 32 ou 64 bits) qui est un pointeur sur une structure connue de la poubelle, comme étant associé aux données de l'objet renvoyé. . P>
Si vous souhaitez regarder directement les références, l'outil à faire est le débogueur. Chargez votre code C # dans le débogueur, le compilez, exécutez-le, cliquez sur un point d'arrêt et jetez un coup d'œil à l'état de la pile et des registres. Avec un peu d'intelligence, vous devriez être capable de déterminer quels endroits de pile et registres correspondent à quelles variables locales. Les emplacements correspondant aux variables locales de type de valeur contiendront les valeurs; Celles-ci du type de référence contiendront des valeurs qui ressemblent à des pointeurs. Si vous examinez ces pointeurs dans la fenêtre de mémoire, vous examinerez ensuite les structures conservées par le collecteur des ordures décrivant le contenu de l'objet. P>
Je pense qu'il est important de noter que, si les implémentations existantes .NET peuvent stocker des adresses (d'enregistrements d'objet-info) dans des variables de référence, rien ne garantit que les futures versions le feront. Il serait possible, par exemple, que certains bits d'une variable de référence constitueraient une index en sélectionnant l'un des nombreux tas, tandis que d'autres bits étaient un index dans ce tas. Bien qu'un tel système puisse être inefficace avec des processeurs existants, la conception de futurs processeurs autour d'un tel modèle pourrait permettre une utilisation plus efficace du cache. Le code .NET existant ne devrait pas se soucier de ces détails.
@supercat: Absolument. En fait, des références pourraient être mises en œuvre comme des poignées entièrement opaques qui ne sont que significatives dans la mesure où elles indiquent dans une table appartenant à la poubelle; Il n'y a aucune raison pour que n'importe quel bit i> dans une référence doit avoir une signification particulière. Comme cela se produit, dans les implémentations d'aujourd'hui, chaque référence est i> significative car elle peut être interprétée comme un pointeur. Mais cela est sujet à changement à tout moment.
En dehors de la curiosité, tandis que les processeurs existants ne permettraient probablement pas à ce que de telles choses soient très efficaces, je me demande si cela serait utile dans les futurs processeurs d'avoir un tas de petits objets pour des objets dont les données sont 8 (peut-être 16) octets ou moins, Lorsque chaque emplacement dans la table d'objets tiendrait les données d'objet réelles au lieu d'un pointeur. Sur les processeurs existants, il faudrait une instruction supplémentaire pour chaque accès de tasse pour déterminer quel tas toute référence donnée appartenait, mais s'il y avait une instruction "Obtenir une adresse d'objet" qui a utilisé un peu dans la référence pour sélectionner une seule ou double indirection ...
... cela semblerait que cela pourrait améliorer considérablement l'efficacité lors de l'accès à de petits objets. Étant donné que je devinerais que la moitié des instances d'objet dans un programme de fonctionnement typique aura lieu de 16 octets ou moins, sinon 8, éliminez une récupération de mémoire supplémentaire pour chaque objet d'objet semblerait une grosse victoire. Avez-vous une idée si un nouveau processeur pourrait supporter une telle chose?
@supercat: Ce sont des références intéressantes. Je connais très peu à propos de la conception matérielle; La plupart de mes interactions sont avec des machines virtuelles. Il serait intéressant de mettre ces questions à un expert en architecture du processeur.
La seule chose que vous verriez est une adresse, un nombre apparemment aléatoire. Pourquoi voudriez-vous voir cela?
Pour cimenter l'idée que dans la variable n'est pas l'objet qu'ils définissent, mais plutôt une adresse. Comment allons-nous accéder à cela?
Stackoverflow.com/Questtions/1978232/...
@ m.edmonson, confondu à votre question. C'est fondamental à .NET que l'adresse physique d'un objet est sujette à modifier chaque fois que le GC fait une marque et un balayage. C'est une qualité éphémère dans laquelle les développeurs n'ont aucun intérêt.
L'adresse est un Détail de la mise en œuvre . Il est important de comprendre les différences de comportement plutôt que d'avoir raccroché sur les détails de la mise en œuvre. Il suffit de penser à des types de référence comme "en quelque sorte" pointant vers une valeur plutôt que de tenir la valeur elle-même
Notez que l'adresse d'un objet sur le tas peut changer au fil du temps lorsque le GC déménage l'objet.
blogs.msdn.com/ B / ERICLIPPERT / Archive / 2009/02/17 / ...
@Garryvass Ce n'est pas vrai pour les objets épinglés, de sorte que l'adresse physique d'un objet épinglé est un sens.
@Eugenrieck, tandis que je suis intéressé à savoir si un objet est épinglé, je doute que la connaissance de son emplacement physique m'aidera à récupérer sa mémoire.
Il est également déroutant pour les débutants lorsque vous confondez la déclaration d'un type avec la déclaration d'une variable. "Classe C {}" est la déclaration d'un type. "C C;" est la déclaration d'une variable. De même, il est déroutant de dire «les types de valeur stockent la valeur dans la déclaration». Non. Les types de valeur ne stockent rien, et la déclaration est un morceau de texte dans l'éditeur de code source. Une variable i> de type de valeur stocke la valeur. Il le stocke dans le stockage associé à la variable i>.
@ERICLIPPERT Merci pour votre contribution, je viens de finir de lire votre publication de blog sur les références qui ne sont pas des adresses, une lecture intéressante. J'ai fait vos changements - laissez-moi savoir s'il se lit maintenant avec précision?
@Dykam, Garry Vass: Mon numéro un Pet Hate B> sur Stackoverflow est des gens qui disent "vous ne devriez pas vouloir savoir que". Pourquoi voudriez-vous éminent activement b> curiosité? Soit répondre à la question ou laisser l'OP seul!
@Tomw, je soutiens totalement la curiosité, mais les bonnes conclusions doivent en être tirées. J'ai vu trop souvent quelqu'un enquêter sur un détail et conclure quelque chose de totalement non pertinent. Son commentaire après cela a expliqué pourquoi il voulait, c'est pourquoi j'ai demandé.