2012-01-19 21 views
19

Microsoft.NET framework proporciona la interfaz IDisposable que requiere una implementación del método void Dispose(). Su propósito es permitir la liberación manual o basada en el alcance de recursos costosos que una implementación de IDisposable puede haber asignado. Los ejemplos incluyen colecciones de bases de datos, flujos y manejadores.¿Las implementaciones IDisposable.Dispose() deben ser idempotentes?

Mi pregunta es, si la implementación del método Dispose() fuera idempotente - cuando se llama más de una vez en la misma instancia, la instancia a la que se 'desechará' una sola vez y las siguientes no lanzarán excepciones. En Java, la mayoría de los objetos que tienen un comportamiento similar (nuevamente, las secuencias y las conexiones a la base de datos vienen a mi mente como ejemplos) son idempotentes para su operación close(), que resulta ser el análogo para el método Dispose().

Sin embargo, mi experiencia personal con .NET (y Windows Forms, en particular), muestra que no todas las implementaciones (que son parte del propio marco .NET) son idempotente, de manera que las llamadas posteriores a éstos lanzan una ObjectDisposedException . Esto realmente me confunde sobre cómo se debe abordar la implementación de un objeto desechable. ¿Hay una respuesta común para el escenario o depende del contexto concreto del objeto y su uso?

Respuesta

18

debe a la aplicación del método Dispose() ser idempotente

Sí, lo que debería. No se sabe cuántas veces se llamará.

De Implementing a Dispose Method en MSDN:

un método Dispose debe ser exigibles varias veces sin lanzar una excepción.

Un objeto con una buena aplicación de IDispose tendrá una bandera campo booleano que indica si se ha eliminado ya y en llamadas posteriores hacer nada (ya que ya estaba dispuesta).

+7

El hecho de que Microsoft no siga siempre su propia recomendación no significa que deba hacerlo. – linkerro

+0

@linkerro - ¿Podrías por favor ampliar tu comentario algo críptico? – Oded

+0

Me pregunto si se está refiriendo a que WinForms arrojará una excepción si Deshace un Control dos veces. – DaveShaw

5

From MSDN:

Permitir un método Dispose para ser llamado más de una vez sin lanzar una excepción. El método no debería hacer nada después de la primera llamada.

+3

Quizás debiste haber incluido el siguiente punto para mayor claridad: "Lanzar una ObjectDisposedException desde métodos de instancia en este tipo (que no sea Dispose) cuando los recursos ya están eliminados. Esta regla no se aplica al método Dispose porque debe llamarse varias veces sin lanzando una excepción. " – Jamiec

7

Sí, también asegúrese de que los otros métodos de la clase responden correctamente cuando se invocan cuando el objeto ya se ha eliminado.

public void SomeMethod() 
{ 
    if(_disposed) 
    { 
     throw new ObjectDisposedException(); 
    } 
    else 
    { 
     // ... 
    } 

} 
+0

Ser capaz de hacer frente aquí puede ser simplemente lanzar una excepción. Y no estoy seguro de si se debería requerir algo en absoluto. No requiera que los objetos desechados "funcionen" de alguna manera. Intentar utilizar un objeto eliminado es un error y debe tratarse como tal. –

+0

@ R.MartinhoFernandes - sí, pero todavía es algo que añadir :) –

+0

@ R.MartinhoFernandes, creo que lo que @Emo está diciendo es - si todavía posee una referencia a un objeto ya dispuesto, y llame a algunos de los otros métodos tiene, estos métodos deben arrojar la 'ObjectDisposedException', o notificar a la persona que llama que la operación es ilegal en este estado. Desafortunadamente, creo que esto podría ser un premio de conciencia de sincronización. –

3

Personalmente - Sí - Siempre hago Dispose() idempotent.

Durante el ciclo de vida habitual de un objeto en una aplicación determinada, puede que no sea necesario; el ciclo de vida desde la creación hasta la eliminación puede ser determinístico y bien conocido.

Sin embargo, igualmente, en algunas aplicaciones puede no ser tan claro.

Por ejemplo, en un escenario de decorador: puedo tener un objeto desechable A, decorado con otro objeto desechable B. Me gustaría disponer explícitamente de A, y sin embargo, deshacerme de B también puede disponer de la instancia que envuelve (piense: corrientes).

Dado que es relativamente fácil de hacer Dispose idempotent (es decir, si ya está dispuesto, no hacer nada), parece tonto no hacerlo.

Cuestiones relacionadas