2012-01-19 15 views
19

Il framework Microsoft.NET fornisce l'interfaccia IDisposable che richiede un'implementazione del metodo void Dispose(). Il suo scopo è quello di abilitare il rilascio manuale o basato su scope di risorse costose che potrebbero essere state assegnate all'implementazione IDisposable. Gli esempi includono raccolte di database, flussi e maniglie.Le implementazioni IDisposable.Dispose() dovrebbero essere idempotenti?

La mia domanda è, nel caso in cui l'implementazione del metodo Dispose() sia idempotente, quando viene chiamata più di una volta nella stessa istanza, l'istanza viene "eliminata" una sola volta e le chiamate successive non generano eccezioni. In Java, la maggior parte degli oggetti con comportamento simile (di nuovo flussi e connessioni di database mi vengono in mente come esempi) sono idempotenti per la loro operazione close(), che risulta essere l'analogo per il metodo Dispose().

Tuttavia, la mia esperienza personale con .NET (e Windows Form in particolare), dimostra che non tutte le implementazioni (che sono parte del framework .NET per sé) sono idempotente, in modo che le chiamate successive a questi gettano un ObjectDisposedException . Questo mi confonde davvero su come si dovrebbe avvicinare l'implementazione di un oggetto usa e getta. Esiste una risposta comune per lo scenario o dipende dal contesto concreto dell'oggetto e dal suo utilizzo?

risposta

18

qualora l'attuazione del metodo Dispose() essere idempotente

Sì, dovrebbe. Non si può dire quante volte sarà chiamato.

Da Implementing a Dispose Method su MSDN:

un metodo Dispose dovrebbe essere richiamabili più volte senza un'eccezione.

Un oggetto con una buona implementazione di IDispose avrà un flag campo booleano che indica se è stato eliminato già e chiamate successive non nulla (come è stato già disposto).

+7

Solo perché Microsoft non segue sempre la propria raccomandazione non significa che si dovrebbe. – linkerro

+0

@linkerro - Puoi per favore espandere il tuo commento piuttosto criptico? – Oded

+0

Mi chiedo se si riferisca a WinForms che lancia un'eccezione se Dispose a Control due volte. – DaveShaw

5

From MSDN:

Lasciare un metodo Dispose di essere chiamato più di una volta, senza un'eccezione. Il metodo non dovrebbe fare nulla dopo la prima chiamata.

+3

Forse avresti dovuto includere il prossimo punto per maggiore chiarezza: "Lancia una ObjectDisposedException da metodi di istanza su questo tipo (diversi da Dispose) quando le risorse sono già disposte. Questa regola non si applica al metodo Dispose perché dovrebbe essere richiamabile più volte senza lanciando un'eccezione. " – Jamiec

7

Sì, assicurarsi anche che gli altri metodi della classe rispondano correttamente quando vengono chiamati quando l'oggetto è già stato eliminato.

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

} 
+0

Essere in grado di far fronte potrebbe essere semplicemente gettare un'eccezione. E non sono davvero sicuro se qualcosa dovrebbe essere richiesto a tutti. Si prega di non richiedere che gli oggetti disposti continuino a "funzionare" in qualche modo. Cercare di utilizzare un oggetto disposto è un bug e dovrebbe essere trattato come tale. –

+0

@ R.MartinhoFernandes - sì ma è ancora qualcosa da aggiungere :) –

+0

@ R.MartinhoFernandes, penso che cosa sta dicendo @Emo è - se si dispone ancora di un riferimento a un oggetto già disposto, e chiamare alcuni degli altri metodi ha, questi metodi dovrebbero lanciare 'ObjectDisposedException', o comunque notificare al chiamante che l'operazione è illegale per questo stato. Sfortunatamente, credo che questo potrebbe venire ad un premio di consapevolezza sinchronization. –

3

Personalmente - Sì - Apporto sempre Dispose() idempotente.

Durante il solito ciclo di vita di un oggetto in una determinata applicazione potrebbe non essere necessario - il ciclo di vita dalla creazione fino alla dismissione può essere deterministico e ben noto.

Tuttavia, ugualmente, in alcune applicazioni potrebbe non essere così chiaro.

Ad esempio, in uno scenario decoratore: potrei avere un oggetto monouso A, decorato da un altro oggetto monouso B. Potrei voler disporre esplicitamente A, e tuttavia Dispose su B può anche disporre dell'istanza che avvolge (pensa: flussi).

Dato che è relativamente facile eseguire Dispose idempotent (cioè se già disposto, non fare nulla), sembra sciocco non farlo.

Problemi correlati