2010-12-30 9 views
5
interface IMyInterace 
{ 
void Open(); 
object Read(); 
void Close(); 
} 

class MyImplementation : IMyInterface 
{ 
public void Open() { /* instantiates disposible class */ } 
//... 
public void Close() { /* calls .Dispose(); */ } 

} 

¿Hay una buena manera de manejar este tipo de situaciones para garantizar que se llamen las instancias desechables dentro de la clase? (No hay señal para las personas que llaman que deben llamar 'Cerrar' excepto en la documentación.) Las implementaciones de IMyInterface no necesariamente encapsulan las instancias IDisposible y se cierran y vuelven a abrir repetidamente a lo largo de la vida de la aplicación.¿Cómo tratar con una clase que encapsula una instancia desechable?

Estoy pensando en hacer esto:

  • Implementar IDisposible en MyImplementation.
  • Set Dispose() para llamar a Close().
  • Agregue una llamada a Cerrar() o Desechar() al que comienza de Abierto para asegurar que la llamada anterior se cerró.

Los usuarios de IMyInterface no saben qué aplicación que están utilizando, así que no estoy seguro de cuánto tiene el valor de hacer disposible MyImplementation, y de nuevo, no todas las implementaciones encapsular IDisposibles.

Respuesta

1

Además de las respuestas que ya están aquí:

Si esta clase es (a menudo/a veces) utilizado solo a través de la interfaz, aconsejaría heredar IMyInterace de IDisposable.

Eso permitirá que los usuarios usen estos objetos de manera consistente. El inconveniente es, por supuesto, que puede necesitar agregar (ficticio) Descartar métodos a clases que realmente no lo necesitan. Pero el beneficio está en la coherencia y la flexibilidad: ¿qué pasa si una clase cambia en el futuro para que necesite un Dispose()?

Un enfoque mínima:

interface IMyInterace : IDisposable { } 

sealed class MyImplementation : IMyInterface 
{ 
    public void Open() { /* instantiates disposible class */ } 

    public void Close() { /* calls _myField.Dispose(); */ } 

    public void Dispose() { Close(); } // only use this short form in a sealed class 

} 
5

La forma estándar de manejar esto es simplemente tener MyImplementation implementar IDisposable.

3

Como mencionó John, su primer punto es el correcto.

A veces, un método Close() es funcionalmente sinónimo de Dispose(), y existe para mantener la coherencia semántica con una abstracción. Es decir, para complementar un método Open(). Otras veces, Close() le permitirá volver a abrir, pero Dispose() no debería. Su segunda viñeta está, por lo tanto, bien también.

El punto de viñeta 3 no es necesariamente aplicable, porque un objeto eliminado no debe reutilizarse. Si necesita llamar al Open() nuevamente, necesita usar una nueva instancia. De hecho, el método Open() debe arrojar un ObjectDisposedException una vez que se ha llamado a Dispose() (al marcar un indicador booleano privado disposed). Si desea que el objeto sea compatible con la reapertura después de cerrar, puede considerar usar Debug.Assert() y/o lanzar una excepción si se llama al Open() sin Close(). Esto ayudará a evitar la administración descuidada de estas instancias.

Asegúrese de seguir el patrón desechable lleno, lo que es más complicado que simplemente implementando la interfaz:

bool disposed; 

public void Dispose() // don't make virtual! 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

protected virtual void Dispose(bool disposing) 
{ 
    if(!disposed) 
    { 
     if(disposing) 
     { 
      // dispose of managed resources here, for example: 
      // if(resource != null) { resource.Dispose(); } 
     } 
    } 

    // dispose of unmanaged resources here 

    disposed = true; 
} 
+2

No es necesario el patrón desechable lleno.No es necesario un destructor y, por lo tanto, no para SuprimirFinalizar. –

Cuestiones relacionadas