2009-11-09 15 views
5

Hace muchos años, se me advirtió, siempre que sea posible, liberar recursos en orden inverso a cómo se asignaron. Es decir:C#: ¿Existe una ventaja para la eliminación de recursos en el orden inverso de su asignación?

block1 = malloc(...); 
block2 = malloc(...); 

... do stuff ... 

free(block2); 
free(block1); 

imagino en una máquina de 640 KB de MS-DOS, esto podría minimizar la fragmentación del montón. ¿Hay alguna ventaja práctica de hacer esto en una aplicación C# /.NET, o es este un hábito que ha sobrevivido a su relevancia?

Respuesta

5

Si sus recursos se crean bien, esto no debería importar (mucho).

Sin embargo, muchas bibliotecas poco creadas no realizan la comprobación adecuada. La eliminación de los recursos a la inversa de su asignación generalmente significa que usted está eliminando recursos dependientes de otros recursos primero, lo que puede evitar que las bibliotecas mal escritas causen problemas. (Nunca descarte un recurso, luego use uno que dependa de la existencia del primero en este caso).

También es una buena práctica, ya que no va a tirar accidentalmente un recurso requerido por otro objeto demasiado pronto .

Aquí hay un ejemplo: observe una operación de base de datos. No desea cerrar/eliminar su conexión antes de cerrar/eliminar su comando (que usa la conexión).

+0

Bien creado no es bueno. Tiene que depender del pedido, depende del lanzamiento y se conoce en muchas circunstancias. No podría importar más en todas las implementaciones de bases de datos, transacciones y cualquier cosa que se ejecute en una pila (la mayoría del software). Las cerraduras son otro ejemplo y hay montones de bibliotecas no externas y no pobres que lo usan. Las operaciones de archivo y sus bloqueos son otra. Fugas de eventos otra. Cualquier recurso no gestionado dependiendo de otro. La creación y la destrucción van de la mano, y la expresión idiomática no se puede interpretar como Inicialización de los recursos: es "bien-creación". –

+0

Para que el WC en oxímoron RIIWC se reemplace por Adquisición, lo que implica una Liberación por cierto. Y dado que la memoria y la gran cantidad de recursos son en su mayoría abstraídos, ops, ahí va la idea ... y se producen intrusiones de todo tipo. En pocas palabras, es simplemente la naturaleza del problema y es muy importante. –

+0

Y aunque no estoy defendiendo la dependencia del orden aquí, la observación correcta es que es muy relevante pero raramente deseable. Pero es algo que incluso las especificaciones oficiales de VM están extremadamente restringidas. Java impl especialmente y CLR a un nivel menor, pero aún significativo. Es un truco no romper grandes cantidades de códigos de trabajo y suposiciones hechas, una decisión consciente por el compilador y los diseñadores de back-end jit. El código que es capaz de procesar independientemente de la orden se presta a una gran variedad de posibilidades, pero puede ser inviable para muchos escenarios. –

4

No te molestes. El GarbageCollector se reserva el derecho de desfragmentar y mover objetos en el montón, por lo que no se sabe en qué orden están las cosas.

Además, si elimina las referencias A y B y A B no debería importar si A descarta B cuando descarta A, ya que el método Dispose debería llamarse más de una vez sin que se produzca una excepción.

+1

es cierto, siempre y cuando no utilice un "dispuesto "referencia por accidente (a través de otro objeto creado a partir de ella), ya que dispone en ord arbitrario er. –

0

'Usings' anidados muestra que el 'outlived' no está realmente encendido, y rara vez es (no ir y decir nunca después de 40 años de evidencia) .. Y eso incluye la máquina virtual basada en pila que se ejecuta en CMOS decir .

[A pesar de algunos intentos de MSDN.com y Duffius para hacer que desaparezca, usted sabe administrarlo todo para usted la diferencia entre el montón y la pila. Qué idea tan inteligente ... en el espacio]

1

Si se refiere a la hora en que se llama al destructor en los objetos, entonces eso depende del recolector de basura, la programación puede tener muy poca influencia sobre eso, y es explícitamente no determinista según la definición del lenguaje.

Si se refiere a llamar IDisposable.Dispose(), eso depende del comportamiento de los objetos que implementan la interfaz IDisposable.

En general, el pedido no es importante para la mayoría de los objetos de Framework, excepto en la medida en que sea importante para el código de llamada. Pero si el objeto A mantiene una dependencia en el objeto B, y el objeto B está dispuesto, entonces podría ser importante no hacer ciertas cosas con el objeto A.

En la mayoría de los casos, no se llama a Dispose() directamente, más bien, se denomina implícitamente como parte de una declaración using o foreach, en cuyo caso el patrón de orden inverso surgirá de forma natural, de acuerdo con la incrustación de la declaración.

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. 
} 
0

"El tiempo de ejecución no hace ninguna garantía en cuanto al orden en que son llamados métodos Finalizar. Por ejemplo, digamos que es un objeto que contiene un puntero a un objeto interno.El recolector de basura ha detectado que ambos objetos son basura. Además, di que el método Finalize del objeto interno se llama primero. Ahora, el método Finalize del objeto externo tiene permiso para acceder al objeto interno y llamar a métodos sobre él, pero el objeto interno se ha finalizado y los resultados pueden ser impredecibles. Por esta razón, se recomienda encarecidamente que los métodos Finalizar no acceda a ninguna, objetos miembro interior."

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

Así que usted puede preocuparse de sus LIFO disponer semántica que todo lo que quiera, pero si hay fugas uno, el Dispose() 's van a ser llamados en el orden que las fantasías CLR.

(Esto es más o menos lo que dijo Will, arriba)

Cuestiones relacionadas