C #: Y a-t-il un avantage à disposer les ressources en ordre inverse de leur allocation?

Il y a de nombreuses années, j’ai été exhorté à libérer autant que possible les ressources dans l’ordre inverse de leur répartition. C’est:

block1 = malloc( ... ); block2 = malloc( ... ); ... do stuff ... free( block2 ); free( block1 ); 

J’imagine que sur une machine MS-DOS 640K, cela pourrait minimiser la fragmentation du tas. Y a-t-il un avantage pratique à le faire dans une application C # / .NET ou s’agit-il d’une habitude qui a perdu sa pertinence?

    Si vos ressources sont bien créées, cela ne devrait pas avoir d’importance.

    Cependant, beaucoup de bibliothèques mal créées ne font pas les vérifications nécessaires. La disposition des ressources en sens inverse de leur affectation signifie généralement que vous disposez en premier de ressources dépendantes d’autres ressources, ce qui peut empêcher les bibliothèques mal écrites de causer des problèmes. (Vous ne disposez jamais d’une ressource, puis utilisez-en une qui dépend de son existence dans ce cas.)

    C’est également une bonne pratique, car vous n’allez pas éliminer par inadvertance une ressource requirejse par un autre object trop tôt.

    Voici un exemple: regardez une opération de firebase database. Vous ne voulez pas fermer / supprimer votre connexion avant de fermer / supprimer votre commande (qui utilise la connexion).

    Ne t’embête pas. GarbageCollector se réserve le droit de défragmenter et de déplacer des objects sur le tas, de sorte que rien ne permet de savoir dans quel ordre se trouvent les objects.

    De plus, si vous disposez des références A et B et A des références B, le fait que A supprime B lorsque vous disposez de A ne devrait pas avoir d’importance, car la méthode Dispose doit pouvoir être appelée plusieurs fois, sans exception.

    Si vous vous référez au moment où le destructeur sur les objects est appelé, alors cela revient au récupérateur de mémoire, la programmation peut avoir très peu d’influence sur cela, et c’est explicitement non déterministe selon la définition du langage.

    Si vous faites référence à l’appel de IDisposable.Dispose (), cela dépend du comportement des objects qui implémentent l’interface IDisposable.

    En général, l’ordre n’a pas d’importance pour la plupart des objects Framework, sauf dans la mesure où cela importe pour le code appelant. Mais si l’object A maintient une dépendance sur l’object B et que l’object B est disposé, il pourrait alors être très important de ne pas faire certaines choses avec l’object A.

    Dans la plupart des cas, Dispose () n’est pas appelé directement, mais plutôt implicitement dans le cadre d’une instruction using ou foreach. Dans ce cas, le modèle d’ordre inverse apparaîtra naturellement, en fonction de l’intégration de l’instruction.

     using(Foo foo = new Foo()) using(FooDoodler fooDoodler = new FooDoodler(foo)) { // do stuff // ... // fooDoodler automatically gets disposed before foo at the end of the using statement. } 

    Les “utilisations” nestedes vous montrent que le “dépassé” n’est pas vraiment actif et qu’il l’est rarement (pour ne pas dire jamais après 40 ans de preuves). Et cela inclut la machine virtuelle basée sur une stack qui s’exécute sur une CMOS.

    [Malgré quelques tentatives de MSDN.com et de Duffius pour le faire disparaître, vous savez gérer pour vous la différence entre le tas et la stack. Quelle idée intelligente .. dans l’espace]

    “Le moteur d’exécution ne donne aucune garantie quant à l’ordre dans lequel les méthodes Finalize sont appelées. Par exemple, supposons qu’un object contient un pointeur sur un object interne. Le garbage collector a détecté que les deux objects sont des déchets. , disons que la méthode Finalize de l’object interne est appelée en premier lieu. Désormais, la méthode Finalize de l’object externe est autorisée à accéder à cet object et à l’appel de ses méthodes, mais l’object interne a été finalisé et les résultats peuvent être imprévisibles. Pour cette raison, il est fortement recommandé que les méthodes Finalize n’accèdent à aucun object membre interne. ”

    http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

    Ainsi, vous pouvez vous inquiéter autant que vous le souhaitez de votre sémantique LIFO, mais si vous en perdez une, les Dispose () seront appelées dans l’ordre de votre choix.

    (C’est plus ou moins ce que Will a dit, ci-dessus)