2009-11-20 23 views
13

Como desarrollador de Java ingresando a .NET, me gustaría entender la interfaz IDisposable. ¿Podría alguien tratar de explicar esto y cómo difiere de lo que sucede en Java? Gracias.Metáfora identificable en Java?

Respuesta

17

Escribí un detailed series of articles on IDisposable.

La idea básica aquí es que a veces se necesita DETERMINADO DISPOSICIÓN DE LOS RECURSOS. IDisposable proporciona ese mecanismo.

Por ejemplo, supongamos que tiene un control en una ventana. Cuando se crea esto, crea un identificador de Windows (HWND) internamente. Cuando quita el control de la ventana y ya no se usa, el control pasa a ser elegible para la recolección de basura, pero no se recoge de inmediato. De hecho, no hay garantías de cuánto tiempo pasará antes de que se recopile.

Hasta que el GC se ejecute y procese el control huérfano, seguirá utilizando recursos, ya que aún contiene el HWND.

IDisposable proporciona un medio para que los objetos que contienen código que necesita limpieza separada del GC se limpien explícitamente por el usuario del objeto. En el caso del control, podemos llamar al myControl.Dispose(),, que limpiará de forma inmediata y sincrónica los recursos "nativos" (HWND) utilizados por el control.

+2

Pregunta rápida: ¿cómo se puede saber si un recurso no está administrado y debe eliminarse explícitamente? – gil

+3

Ver si implementa IDisposable. :) Bastante siempre siempre desecha tus ID, si puedes. –

+0

Si no se administra el recurso, debe saberlo cuando implemente la clase. Si no lo está implementando, solo lo usa, entonces no se requiere cuidado especial. Si necesita decidir sobre la eliminación explícita, intente responder a la pregunta "¿Es más urgente liberar el recurso lo antes posible que continuar la ejecución en este hilo ahora mismo?". Las respuestas pueden ser diferentes, por ejemplo, para una parte del servicio web frente a una parte de la GUI. –

-3

No hay equivalente.

Se utiliza cuando utiliza recursos no administrados (en Java todos los recursos gestionados son).

In. La memoria de red asignada por los recursos administrados es recopilada automáticamente por el GC (como en Java).

También tiene la oportunidad de utilizar recursos no administrados, donde será responsable de la asignación de memoria y su lanzamiento.

Llama a este método cuando ya no necesita los recursos.

7

Hay situaciones en las que necesita una eliminación confiable de los recursos que pertenecen a su clase. Por ejemplo, la conexión abierta debe cerrarse en el momento adecuado, no cuando GC decide recopilar memoria. En .NET método Dispose es utilizado por la convención para esto. Se le puede llamar en try ... finally bloque, por ejemplo:

IConnection conn = OpenConnection(); 
try{ 
    ... 
}finally{ 
    conn.Dispose(); 
} 

Debido a este patrón es tan ampliamente utilizado, hay un azúcar sintáctico para esto:

using(IConnection conn = OpenConnection()){ 
} // Dispose is called at the end. 

Como esta sintaxis es muy concisa, a veces es útil para implemente IDisposable en objetos que no poseen recursos, pero necesitan ejecutar alguna operación al final de su uso. P.ej. tener en cuenta la clase

class TimeMeasure: IDisposable{ 
    public void Measure(string operation) { ... } // recourds operation time 
    public void Dispose(){ 
     ... // print timings for all operations 
    } 
} 

Uso:

using(TimeMeasure m = new TimeMeasure()) 
{ 
    DoFoo(); 
    m.Measure("Foo"); 
    DoBar(); 
    m.Measure("Bar"); 
} // timings for 'Foo' and 'Bar' are printed here 

En Java interfaz más o menos equivalente es Closeable. Pero no hay una sintaxis simple para garantizar sus llamadas.

¿Cómo se debe implementar IDisposable?Esto es un poco complicado:

  • si posee los recursos, es necesario asegurarse de que pueden ser liberados por explícita Dispose llamada o por GC, pero no por ambos. Entonces, necesitas una bandera que indique el hecho de la eliminación. Para una menor duplicación de código, el código de eliminación se mueve a un método diferente.

Ejemplo:

bool disposed; 
public void Dispose(){ 
    Dispose(true); 
    GC.SuppressFinalize(this); // tell GC not to call Finalizer() for this object 
} 

~MyObject(){ 
    Dispose(false); 
} 

void Dispose(bool manualDisposing){ 
    if(!disposed){ 
     disposed = true; 
     if(manualDisposing) 
      ... // call Dispose on all IDisposable fields 
     ... // dispose all native resources 
    } 
} 
  • si no está sujetando los recursos, como en el caso de TimeMeasure clase, sin necesidad de finalizador, que acaba de hacer la lógica necesaria en Dispose.
2

Básicamente IDisposable en un nivel alto, combinado con la palabra clave using le está dando soporte sintáctico de lo que se ve como un lenguaje de Java común como esto:

Connection c = null; 
    try { 
     c = getConnection(); 
     .... 
    } finally { 
     if (c != null) { 
      c.close(); 
     } 
    } 

Si Java tenía un uso de la palabra clave y una interfaz IDisposable con un método close(), que podría tener este aspecto:

//psudo-Java 
    using(Connection c = getConnection()) { 
     ..... 
    } 

con el método de cierre se llama implícitamente al final de ese bloque. No hay necesidad de probar/finalmente.

Dicho esto, IDisposible tiene un contrato bastante complejo, y se trata principalmente de liberar la memoria no administrada. Tienes que trabajar duro con Java para tener memoria no administrada (básicamente con componentes JNI y Swing, tienes el concepto), pero es mucho más común en .NET, por lo que hay soporte de lenguaje para el concepto.

11

Con java 1.7 aparece la nueva instrucción try-with-resource.

try (BufferedReader br = new BufferedReader(new FileReader(path))) { 
    return br.readLine(); 
} 

Los objetos utilizados aquí deben implementar la interfaz AutoCloseable. No es exactamente lo mismo que IDisposable, pero el close() se llama automáticamente en el final. Esto le da la oportunidad de implementar un comportamiento similar.

El código anterior es la misma que

BufferedReader br = new BufferedReader(new FileReader(path)); 
try { 
    return br.readLine(); 
} finally { 
    if (br != null) br.close(); 
} 

Leer más sobre esto en java tutorial. El código de ejemplo proviene de allí.

+0

Esta debería ser la respuesta aceptada. No solo explica cómo funciona el concepto desechable, sino que muestra cómo esto se implementa en Java. Todas las demás respuestas solo hacen referencia al mecanismo C#. – JavierIEH

+0

AutoCloseable no AutoClosable – Sonny

0

La interfaz IDisposable se utiliza para liberar manualmente los recursos no administrados.