Pregunta

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 hacer frente a este tipo de situaciones para asegurar que las instancias de la clase dentro disposible ser llamado? (No hay señal de que las personas que llaman que deben llamar 'Cerrar', excepto en la documentación.) Las implementaciones de IMyInterface no necesariamente casos encapsulado IDisposible y se cierran y se volvieron a abrir repetidamente a lo largo de la vida de la aplicación.

Estoy pensando en hacer esto:

  • Implementar IDisposible en MyImplementation.
  • Conjunto Dispose () para llamar a Close ().
  • Añadir una llamada a Close () o Dispose () a la INICIO DE abierta para asegurar anterior llamada fue cerrado.

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

¿Fue útil?

Solución

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

Si esta clase es (a menudo / a veces) se utiliza a través de la interfaz sólo yo aconsejaría a IMyInterace Heredar del IDisposable.

Esto le permitirá a sus usuarios utilizan estos objetos de una manera consistente. El inconveniente es, por supuesto, que usted puede necesitar agregar (dummy) Desechar los métodos de clases que en realidad no lo necesitan. Sin embargo, el beneficio está en la consistencia y flexibilidad: ¿Qué pasa si una clase cambia en el futuro, por lo que necesita un Dispose ()

?

Un enfoque mínimo:

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

}

Otros consejos

La forma estándar para manejar esto es simplemente tener MyImplementation aplicar IDisposable.

Como Juan mencionó, el primer punto es 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. por lo tanto su segunda bala-punto está bien, también.

punto 3 de la bala no es necesariamente el caso, debido a que un objeto desechado no debe ser reutilizado. Si necesita Open() llamada de nuevo, es necesario utilizar una nueva instancia. De hecho, el método Open() debe lanzar una vez ObjectDisposedException Dispose() han sido llamados (marcando un disposed privada bandera booleana). Si desea que el objeto de apoyo reapertura tras el cierre, es posible considerar el uso de Debug.Assert() y / o lanzar una excepción si se llama Open() sin Close(). Esto ayudará a evitar que la gestión descuidada de estos casos.

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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top