2009-12-29 13 views
6

Sto lavorando a un progetto .NET, che deve interagire con alcune classi definite dall'utente, denominate "lavori". Tutte le classi di lavoro devono implementare un'interfaccia specifica IJob nell'ordine in cui la libreria può consumarle. A volte una classe di lavoro può contenere risorse non gestite, che devono essere disposte esplicitamente.Come dovrei garantire lo smaltimento di eventuali oggetti monouso?

In che modo è necessario garantire che tutti i lavori siano correttamente smaltiti dopo l'uso, se non si conosce in anticipo se il lavoro richiede uno smaltimento esplicito? Ho un paio di idee me stesso, ma vorrei sentire i vostri commenti/suggerimenti:

  1. Fai IJob : IDisposable, costringendo tutti i lavori per implementare un metodo Dispose(). Ciò mi consentirà di lavorare con i lavori nei blocchi using, ma poiché la maggior parte dei lavori è non che si prevede abbia bisogno di smaltimento esplicito, ciò potrebbe aggiungere confusione non necessaria per gli sviluppatori client.

  2. fare tutto il lavoro che coinvolge posti di lavoro in try-finally blocchi, e utilizzare finally per garantire che Dispose() si chiama se il lavoro implementa IDisposable. Ciò rende più semplice per i clienti implementare una nuova classe di lavoro - non dovendo implementare un metodo vuoto Dispose() - ma nasconde anche il fatto che la libreria conosce e si preoccupa dei lavori usa e getta.

Dopo aver scritto questo, ho tendono a inclinarsi verso la soluzione # 1, ma io continuo a pensare che sarebbe stato bello vedere soluzioni alternative, e pro supplementari/svantaggi di due ho già in mente.

risposta

8

C'è un precedente: La classe di base Stream è nad IDisposable quindi tutti i discendenti flussi sono . Ma MemoryStream non ha bisogno di Smaltimento.
Ma non mirare a try/finally, il blocco using() { } è una stenografia più comoda.

Quindi la tua scelta è: vuoi che tutti i lavori siano IDisposabili o solo alcuni?

La prima opzione comporta un piccolo overhead, la seconda rende più facile dimenticare Dispose (utilizzando) quando è necessario.

+0

Buon punto. Tuttavia, la maggior parte dei flussi avrà bisogno di smaltimento, e mi aspetto che solo una minoranza di posti di lavoro ne abbia bisogno. –

+0

Mi viene in mente che 'System.Web.IHttpModule' richiede anche ai suoi implementatori di fornire un metodo' Dispose() ', anche se solo pochi moduli (IMHO) ne hanno bisogno. Immagino che questo preveda un'ulteriore precedenza per il # 1. –

+1

+1, penso inoltre che abbia senso fornire un metodo standardizzato per un lavoro per ripulire ciò che ha usato. Usando 'IDisposable' puoi beneficiare del supporto del framework e gli utenti finali possono trarre beneficio dal dover posizionare correttamente il codice cleanup. – user7116

2

Vorrei andare con il n. 2 e documentare che qualsiasi oggetto disponibile sarà smaltito. Fondamentalmente se si diventa proprietari di un oggetto si è obbligati a disporre di oggetti che implementano IDisposable.

Se andate a leggere Effective C#/più efficace C#, Bill Wagner dare lo stesso consiglio (che sono d'accordo con ovviamente ;-)

+0

L'OP è già disponendo gli oggetti di proprietà di entrambe le opzioni, quindi non vedo come questo è un argomento per l'opzione # 2. –

3

Ci penso in questo modo. Preferirei che uno sviluppatore implementasse un metodo vuoto Dispose piuttosto che dimenticare di implementare un metodo Dispose necessario.

5

# 2 è il modo in cui il costrutto foreach funziona. È anche il modo in cui funziona lo smaltimento dei container di Autofac.

La differenza semantica è se si dice che un lavoro per sé è usa e getta, o se un'implementazione potrebbe essere usa e getta.

È chiaro dal tuo esempio che il primo non è vero, che i lavori non sono intrinsecamente usa e getta.Pertanto, vi consiglio # 2, ma con un metodo di estensione per centralizzare la try/finally:

public static void Execute(this IJob job) 
{ 
    try 
    { 
     job.Run(); 
    } 
    finally 
    { 
     var disposableJob = job as IDisposable; 

     if(disposableJob != null) 
     { 
      disposableJob.Dispose(); 
     } 
    } 
} 
+0

+1, mi piace la tua argomentazione sulla semantica, ma penso che andrò con la prima soluzione, per le ragioni menzionate nelle altre risposte e nella domanda stessa. –

Problemi correlati