Question

Devriez-vous mettre tous les objets de null (Nothing dans VB.NET) une fois que vous avez fini avec eux?

Je comprends que dans .NET, il est essentiel de disposer de toutes les instances des objets qui implémentent l' IDisposable interface pour libérer quelques ressources bien que l'objet peut-être encore quelque chose après il est disposé (d'où le isDisposed propriété dans les formulaires), je suppose qu'il peut encore résider dans la mémoire ou au moins en partie?

Je sais aussi que quand un objet est hors de portée, il est alors marqué pour la collection prêt pour le prochain passage du garbage collector (même si cela peut prendre du temps).

Donc, avec cela à l'esprit la mise à null accélérer le système en libérant de la mémoire qu'il n'a pas de travail qu'il n'est plus dans le champ d'application et sont-ils de mauvais effets secondaires?

Articles MSDN ne jamais faire cela dans les exemples et actuellement je fais ce que je ne peux pas voir le mal.Cependant, j'ai trouvé un mélange d'opinions afin de tous les commentaires sont utiles.

Était-ce utile?

La solution

Karl est tout à fait exact, il n'est pas nécessaire de définir des objets à null après l'utilisation.Si un objet implémente IDisposable, assurez-vous juste que vous appelez IDisposable.Dispose() lorsque vous avez terminé avec cet objet (enveloppé dans un try..finally, ou, un using() le bloc).Mais même si vous ne vous souvenez pas de l'appeler Dispose(), le finaliser la méthode sur l'objet de l'appel Dispose() pour vous.

Je pensais que c'était un bon traitement:

Creuser dans IDisposable

et ce

La Compréhension IDisposable

Il n'y a aucun point dans l'essai de deuxième deviner le gouvernement du canada et ses stratégies de gestion parce que c'est l'auto tuning et opaque.Il y avait une bonne discussion sur le fonctionnement interne avec Jeffrey Richter sur Dot Net Rochers ici: Jeffrey Richter sur le Modèle de Mémoire de Windows et Richters livre CLR via C# le chapitre 20 est un excellent traitement:

Autres conseils

Une autre raison pour éviter de mettre des objets de valeur null lorsque vous avez terminé avec eux, c'est qu'il peut effectivement garder en vie plus longtemps.

par exemple

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

permettra à l'objet visé par someType à GC avais après l'appel à "DoSomething" mais

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

peut parfois garder l'objet en vie jusqu'à la fin de la méthode.L' JIT généralement optimisé loin de l'affectation à la valeur null, de sorte que les deux bouts de code finissent par être le même.

Non ne sont pas des objets nuls.Vous pouvez consulter http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx pour plus d'informations, mais de remettre les choses à null ne sera pas de tout, sauf de sale votre code.

Aussi:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

En général, il n'y a pas besoin d'objets null après l'utilisation, mais dans certains cas je trouve que c'est une bonne pratique.

Si un objet implémente IDisposable et est stocké dans un champ, je pense que c'est bon null, juste pour éviter à l'aide de l'objet supprimé.Les bugs du tri suivant peut être douloureux:

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

C'est bon à null le terrain après l'élimination, et obtenir une NullPtrEx droit à la ligne où le champ est utilisé à nouveau.Sinon, vous risquez de rencontrer quelques cryptique bug sur la ligne (selon exactement ce DoSomething n').

Les Chances sont que votre code n'est pas structuré de façon assez serrée, si vous en sentez le besoin null les variables.

Il y a un certain nombre de façons de limiter la portée d'une variable:

Comme mentionné par Steve Tranby

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

De même, vous pouvez tout simplement utiliser des accolades:

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

Je trouve qu'à l'aide d'accolades, sans "tête" pour vraiment nettoyer le code et de le rendre plus compréhensible.

Le seul moment où vous devez définir une variable à la valeur null est lorsque la variable n'est pas hors de portée et que vous n'avez plus besoin des données associées.Sinon, il n'est pas nécessaire.

En général, pas besoin de mettre à null.Mais supposons que vous disposez d'une fonctionnalité de Réinitialisation de votre classe.

Alors vous pourriez le faire, parce que vous ne voulez pas appeler dispose deux fois, depuis quelques de la dispose peut-être pas mis en œuvre correctement et de le jeter Système.ObjectDisposed exception.

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }

ce genre de "il n'est pas nécessaire de définir des objets à null après l'utilisation" n'est pas tout à fait exacte.Il y a des fois vous avez besoin de la valeur NULL à la variable après le disposer.

Oui, vous devriez TOUJOURS faire appel à .Dispose() ou .Close() sur tout ce qui a lorsque vous avez terminé.Soit les descripteurs de fichiers, connexions de base de données ou des objets.

Séparé de celui qui est le très pratique modèle de LazyLoad.

Dire que j'ai et instancié ObjA de class A. Class A a une propriété publique appelée PropB de class B.

En interne, PropB utilise la variable privée de _B et la valeur par défaut est null.Lorsque PropB.Get() est utilisé, il vérifie pour voir si _PropB est nulle et si elle l'est, ouvre les ressources nécessaires pour instancier un B en _PropB.Il retourne ensuite _PropB.

De mon expérience, c'est vraiment un bon truc.

D'où la nécessité de null vient en est que si vous changer ou réinitialiser Une certaine façon que le contenu de _PropB ont été à l'enfant les valeurs précédentes de A, vous aurez besoin de les Éliminer ET null hors _PropB donc LazyLoad pouvez le réinitialiser pour récupérer la bonne valeur SI le code l'exige.

Si vous ne le faites _PropB.Dispose() et peu de temps après s'attendre à l'null vérifier LazyLoad pour réussir, il n'est pas null, et vous serez à la recherche à des données périmées.En effet, vous devez null après Dispose() juste pour être sûr.

Je vous souhaite qu'il en était autrement, mais j'ai le code de droit maintenant exposer ce problème après un Dispose() sur un _PropB et à l'extérieur de la fonction appelante qui ne dispose (et donc presque hors de portée), le privé prop n'est toujours pas la valeur null, et les données obsolètes est toujours là.

Finalement, les éliminés de la propriété sera nulle, mais qui est non-déterministe, de mon point de vue.

La raison de base, comme dbkk fait allusion, c'est que le conteneur parent (ObjA avec PropB) est de garder l'instance de _PropB en portée, en dépit de la Dispose().

Il y a certains cas où il est logique de références nulles.Par exemple, lorsque vous écrivez une collection--comme une file d'attente de priorité--et par votre contrat, vous ne devriez pas garder ces objets vivants pour le client après que le client a retiré de la file d'attente.

Mais ce genre de chose uniquement les questions à longue durée de vie des collections.Si la file d'attente ne va pas survivre à la fin de la fonction, il a été créé, alors il importe beaucoup moins.

Sur l'ensemble, vous ne devriez vraiment pas la peine.Laisser le compilateur et GC de faire leur travail de sorte que vous pouvez faire le vôtre.

Jetez un oeil à cet article ainsi: http://www.codeproject.com/KB/cs/idisposable.aspx

Pour la plupart, la définition d'un objet à null n'a aucun effet.Le seul moment où vous devriez être sûr de le faire est si vous travaillez avec un "large object", qui est l'un de plus de 84 taille (comme des images).

Stephen Cleary l'explique très bien dans ce post: Dois-je Définir les Variables à Null pour Aider la Collecte des Ordures?

Dit:

La Réponse Courte, pour les Impatients Oui, si la variable est un champ statique, ou si vous écrivez une énumération méthode (à l'aide de taux de retour) ou une méthode asynchrone (à l'aide de async et await).Sinon, pas de.

Cela signifie que dans les méthodes ordinaires (non énumérable et non-asynchrone), vous ne définissez pas de variables locales, paramètres de la méthode, de l'instance ou de champs à null.

(Même si vous êtes à la mise en œuvre de IDisposable.Jetez, vous ne devez pas définir les variables à null).

La chose la plus importante que nous devons considérer est Les Champs Statiques.

Les champs statiques sont toujours des objets root, de sorte qu'ils sont toujours considéré comme “vivant” par le garbage collector.Si un champ statique fait référence à un objet qui n'est plus nécessaire, elle devrait être nulle, de sorte que le garbage collector traiter comme admissibles pour la collecte.

Réglage statique de champs à null est vide de sens si l'ensemble du processus est en cours d'arrêt.L'ensemble du tas est sur le point d'être nettoyée à ce point, y compris tous les objets root.

Conclusion:

Les champs statiques;c'est à ce sujet.Autre chose est un perte de temps.

Je crois que par la conception de la table des réalisateurs, vous ne pouvez pas vitesse jusqu' GC avec l'annulation.Je suis sûr qu'ils préférez vous inquiétez pas-vous avec comment/quand GC courses -- le traiter comme cette omniprésent Être la protection et de la regarder encore et pour vous...(s'incline la tête en bas, lève le poing vers le ciel)...

Personnellement, j'ai souvent explicitement définir les variables à null quand je suis fait avec eux comme une forme d'auto-documentation.Je n'ai pas de déclarer, à l'utilisation, puis définissez la valeur null à plus tard, je null immédiatement après ils ne sont plus nécessaires.Je suis en train de dire, explicitement, "je suis officiellement fini avec vous...disparu..."

Est de détruire nécessaire dans un GC avais langue?Pas de.Est-il utile pour la GC?Peut-être que oui, peut-être pas, je ne sais pas pour certains, de par leur conception, je ne peux vraiment pas le contrôler, et quel que soit aujourd'hui la réponse à cette version ou que, le futur GC mises en œuvre possible de changer la réponse au-delà de mon contrôle.De Plus, si/lorsque l'invalide est optimisé, c'est un peu plus d'une fantaisie commentaire si vous allez.

Je me dis que si elle me fait une intention plus claire pour la prochaine pauvre imbécile qui suit dans mes pas, et si il "peut-être" potentiellement aider à la GC parfois, alors ça vaut le coup pour moi.Surtout, il me fait me sentir bien rangé et clair, et de Mongo aime à se sentir bien rangé et clair.:)

Je la regarde comme ceci:Les langages de programmation existent pour permettre aux gens de donner d'autres gens une idée de l'intention et un compilateur une demande de travail de quoi faire -- le compilateur convertit cette requête dans une langue différente (parfois plusieurs) pour un CPU -- le CPU(s) pourrait à foutre de ce que la langue utilisée, votre onglet paramètres, commentaires stylistiques, des accents, des noms de variables, etc.- un PROCESSEUR est tout au sujet du flux de bits qui lui dit ce que les registres et les opcodes et emplacements de mémoire pour l'ornement.Beaucoup de choses qui sont écrites dans le code ne se convertit pas en ce qui est consommée par le PROCESSEUR dans la séquence que nous avons spécifié.De notre C, C++, C#, Lisp, Babel, assembleur ou tout ce qui est de la théorie plutôt que de la réalité, écrit comme une déclaration de travaux.Ce que vous voyez n'est pas ce que vous obtenez, oui, même en langage assembleur.

Je comprends l'état d'esprit de "choses inutiles" (lignes vierges) "ne sont rien, mais le bruit et l'encombrement de code." C'était moi, plus tôt dans ma carrière;Je suis totalement d'obtenir.À ce stade, je me penche vers ce qui rend le code plus clair.Ce n'est pas comme je suis en ajoutant même à 50 lignes de "bruit" pour mes programmes -- il est à quelques lignes ici ou là.

Il y a des exceptions à toute règle.Dans les scénarios avec de la mémoire volatile, de mémoire statique, des conditions de course, les singletons, l'utilisation de données "obsolètes et tout ce genre de pourriture, c'est différent:vous avez BESOIN de gérer votre propre mémoire, de verrouillage et de détruire que de propos parce que la mémoire n'est pas une partie de la GC avais Univers espérons que tout le monde comprend cela.Le reste du temps avec GC avais langues, c'est une question de style plutôt que de nécessité ou une garantie de performances.

À la fin de la journée, assurez-vous de comprendre ce qui est admissible pour le GC, et ce qui ne l'est pas;de verrouillage, d'en disposer, et d'annuler de manière appropriée;cire, la cire off;inspirez, expirez;et pour tout le reste, je dis:Si il se sent bien, le faire.Votre kilométrage peut varier...comme il se doit...

Un objet supposons que l' .dispose() méthode des forces de la ressource qui doit être supprimé de la mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top