C # - Les objets sont-ils immédiatement détruits lorsqu'ils sortent de la portée?
Puis-je faire confiance que la destruction d'un objet et de son destructeur est appelé immédiatement quand elle est hors de portée en C#?
Je me dis qu'il doit depuis de nombreuses pratiques de codage (par exemple, des transactions d'objets) s'appuient sur ce comportement, mais je ne suis pas très habitué à travailler avec la collecte des ordures et ont peu d'informations sur la façon dont ces langues se comporter.
Grâce.
source d'informationauteur sharkin
Vous devez vous connecter pour publier un commentaire.
Nope, .Net et C# s'appuie sur une collecte des ordures gestion de la mémoire. Si les destructeurs (qui en .Net est appelé finaliseurs) ne sont pas appelés jusqu'à ce que GC trouve approprié pour détruire les objets.
En outre: la plupart des "réguliers" des objets en C# n'ont pas destructeurs. Si vous avez besoin de le destructeur modèle que vous devriez mettre en œuvre les Interface IDisposable avec le Modèle Dispose. Sur les objets jetables, vous devez également vous assurer que la méthode dispose est appelé, soit avec le à l'aide de mots clés ou en appelant directement la méthode.
De plus (je l'espère) de préciser: déterministe disposition est utile dans les .Net par exemple, lorsque vous devez explicitement gratuit de ressources qui n'est pas géré par l' .Net runtime. Des exemples de ces ressources sont des descripteurs de fichier, de connexions de base de données, etc. Il est généralement important que ces ressources soient libérées dès qu'ils ne sont plus nécessaires. On ne peut donc pas se permettre d'attendre pour la GC gratuit.
Afin d'obtenir déterministe de l'élimination (similaire à la portée comportement de C++) dans le non-déterministe du monde de la .Net GC, l' .Net les classes comptent sur l'interface IDisposable. L'emprunt auprès de la Modèle Disposeen voici quelques exemples:
Tout d'abord, l'instanciation d'un revenu de ressources et de laisser ensuite l'objet hors de portée, laissera à la GC de détruire l'objet:
Pour corriger cela, nous pouvons explicitement détruire l'objet:
Mais que faire si quelque chose se passe mal entre la ligne 2 et 6? Disposer ne sera pas appelé. Enfin, pour garantir que Disposer va enfin être appelés indépendamment de toutes les exceptions, nous pouvons effectuer les opérations suivantes:
Puisque ce modèle est souvent nécessaire, C# inclut l'aide de mot-clé pour simplifier les choses. L'exemple suivant est équivalent à la ci-dessus:
Pas. Un objet n'est pas réellement "hors de portée", la référence (c'est à dire la variable que vous utilisez pour y accéder).
Lorsqu'il n'y a plus de références à un objet donné, l'objet est admissibles pour la collecte des ordures (GC) en cas de nécessité. Chaque fois que le GC décide qu'il a besoin de récupérer l'espace de votre non-plus-objet référencé, c'est quand le finaliseur des objets sera appelée.
Si votre objet est une ressource (par exemple, un descripteur de fichier, la connexion de base de données), il doit implémenter l'interface IDisposable (qui oblige l'objet à mettre en œuvre un
Dispose()
méthode pour nettoyer toutes les connexions ouvertes, etc). La meilleure pratique pour vous dans ce cas serait de créer l'objet en tant que partie d'unusing
bloc, de sorte que lorsque ce bloc est terminé, votre application va automatiquement appeler les objetsDispose()
méthode, qui prendra soin de fermer votre fichier/connexion db/whatever.par exemple
La
using
bloc est à seulement quelques sucre syntaxique qui enveloppe vos interactions avec leconn
objet dans untry
bloc, avec unfinally
bloc qui n'appelleconn.Dispose()
Il n'y a pas une telle chose als C++-comme destructeur en C#. (Il y a un concept différent de destructeur en C#, également appelé un finaliseur, qui utilise la même syntaxe que C++ destructeurs, mais elles ne sont pas liées à la destruction des objets. Ils sont destinés à fournir un mécanisme de nettoyage pour les ressources non managées.)
Le garbage collector de nettoyage des objets peu de temps après ils ne sont plus référencés. Pas immédiatement, et il n'existe aucun moyen de garantir ce soit.
Heureusement, il y a également aucune raison pourquoi vous voulez la garantie. Si vous avez besoin de la mémoire, puis le GC va la récupérer ensuite. Si vous ne le faites pas, pourquoi les soins s'il y a encore peu de déchet de l'objet autour de vous? Ce n'est pas une fuite de mémoire: le GC peut encore la trouver et de la nettoyer tout le temps.
Non, ce n'est pas garanti. Semblables à des langages comme Java, en C# le garbage collector s'exécute lorsque c'est nécessaire (i. e. lorsque le tas est trop plein). Toutefois, lorsque vos objets de mettre en œuvre
IDisposable
j'. e. ils ont unDispose()
méthode et il doit être appelé, alors vous pouvez prendre avantage de lausing
mot-clé:De cette façon
Dispose()
sera appelé immédiatement au moment de quitter queusing
bloc.Remarque:
IDisposable
est trouvé dans de nombreux types, notamment GDI+, mais aussi connexions de base de données, transactions, etc. de sorte qu'il peut vraiment être le bon modèle ici.Note 2: les coulisses de bloc ci-dessus sera traduit dans un
try
/finally
bloc:Mais que la traduction est faite par le compilateur et très pratique pour ne pas oublier d'appeler
Dispose()
.Je ne pense pas que vous devez compter sur des éboueurs de cette façon. Même si vous déduire la façon dont ils fonctionnent, il pourrait très bien être que dans la prochaine version, ils ont ré-implémenté.
Dans tous les cas, les objets ne sont pas des ordures collectées le moment où vous déréférencement. Ils sont généralement recueillies jusqu'à un certain seuil est atteint, et puis ils sont libérés.
En particulier dans les programmes java c'est très visible lorsque vous regardez la consommation de mémoire sur le gestionnaire de tâches. Il grandit et se développe, et tout d'un coup, à chaque minute, il tombe à nouveau.
Pas. Si vous vous reportez à la spécification CLI (p. 8.9.6.7 sur les Finaliseurs) http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf vous pouvez trouver les informations suivantes
mais il ne faut pas.