2009-12-02 19 views
12

Tengo un método que tiene un bloque try/catch/finall dentro. Dentro del bloque try, declaro SqlDataReader como sigue:Llamar a Dispose() frente a cuando sale un objeto scope/method termina

   SqlDataReader aReader = null;   
       aReader = aCommand.ExecuteReader(); 

En el bloque finally, los objetos que están dispuestas de forma manual de son los que se establece en el nivel de clase. Entonces, ¿los objetos del método que implementa IDisposable, como SqlDataReader anterior, se eliminan automáticamente? Se invoca Close() en unReader después de que un ciclo while se ejecuta para obtener el contenido del lector (que debe ser Dispose(), ya que llama a Close()). Si no hay una llamada a Cerrar(), ¿se cerraría/eliminaría este objeto automáticamente cuando el método finaliza o el objeto queda fuera del alcance?

EDIT: Soy consciente de la instrucción using() pero hay situaciones que me confunden. Gracias

Gracias

Respuesta

24

No, los objetos no se eliminan automáticamente cuando salen del alcance.

Ni siquiera están garantizados para ser eliminados si/cuando son recogidos basura, aunque muchos objetos IDisposable implementan un finalizador "de reserva" para ayudar a asegurar que finalmente sean desechados.

Usted es responsable de asegurarse de que cualquier objeto IDisposable esté dispuesto, preferiblemente envolviéndolos en un bloque using.

8

se debe utilizar un bloque de using {...} para envolver los objetos IDisposable en - la Dispose() método (que para SqlDataReader hace pasar al método Close()) será llamado cuando el uso de bloques extremos. Si no se utiliza using, el objeto se no ser eliminado automáticamente cuando se sale del ámbito - que será hasta el finalizador objeto, si tiene uno, para deshacerse de los recursos que se recogen la basura

using (SqlDataReader aReader = aCommand.ExecuteReader()) 
{ 
    // ... do stuff 
} // aReader.Dispose() called here 
-1

¿Podría la declaración Using ayudar?

1

El patrón Dispose no ofrece ninguna garantía sobre qué objetos invocarán Dispose en qué otros objetos; a veces puede suceder, pero no debería importarle. En su lugar, es su responsabilidad asegurarse de que se llame a Dispose() para todos los objetos IDisposables. La mejor manera de hacerlo es con la declaración using. Por ejemplo:

using (SqlDataReader aReader = aCommand.ExecuteReader()) 
{ 
    // your code 
} 
0

Me sorprende la afirmación "En el bloque finally, los objetos que se eliminan manualmente son los que se establecen en el nivel de clase". Por objetos establecidos en el nivel de clase, ¿te refieres a campos? Probablemente no debería deshacerse de estos dentro de un método ordinario, porque entonces la vida útil de los campos es impredecible y depende de qué métodos haya llamado. Sería mejor implementar campos IDisposable y disponer de ellos en su método Dispose.

1

Estoy de acuerdo con todo lo anterior. Debe asegurarse de llamar al Dispose(), y la forma más fácil de hacerlo es con la declaración using (también puede hacerlo usted mismo en el bloque finally; esto es más detallado, pero a veces necesario). Si no lo hace, puede encontrar que su aplicación pierde recursos no administrados, como identificadores o incluso memoria no administrada, especialmente si en algún lugar debajo de todo esto se usan algunos componentes COM o si las llamadas se están realizando en la API de Win32.Obviamente, esto puede generar problemas de rendimiento y estabilidad, así como un uso excesivo de recursos.

El hecho de que los objetos que implementan IDisposable "deben" implementar un finalizador que llama a su método Dispose(bool disposing) para liberar recursos no administrados, no garantiza que esto ocurra, por lo que definitivamente no debe confiar en ello. Consulte, por ejemplo, http://msdn.microsoft.com/en-us/library/b1yfkh5e%28VS.71%29.aspx para obtener más información sobre este punto.

Además, algo más a tener en cuenta es que si su tipo tiene miembros que son desechables, su tipo debe implementar IDisposable (a menos que el ciclo de vida de esos miembros sea administrado por otro tipo, lo que obviamente podría desordenar), o, si solo usa dichos miembros en un método, o para implementar una pieza particular de funcionalidad, debería considerar convertirlos en variables/parámetros locales en los métodos que los utilizan.

Cuestiones relacionadas