2015-04-07 7 views
6

Esistono molti esempi di matrici o elenchi di oggetti IDisposable restituiti da funzioni in .NET. Ad esempio, Process.GetProcesses().Disporre() o Non eliminare() elementi in una matrice di oggetti IDisposable?

  • Se chiamo tale metodo è mia responsabilità Dispose() di tutti i membri dell'array mentre eseguo l'iterazione attraverso di essi?
  • Perché dovrebbe essere una mia responsabilità poiché non ho mai creato gli oggetti e la matrice che mi è stata data è solo un riferimento agli oggetti che sono stati creati al di fuori del mio codice.

Ho sempre pensato che fosse il fardello del creatore a Dispose(). Quindi qual è la regola corretta qui?

+0

Non c'è modo per il 'Creatore' di disporne o parti all'interno delle classi in quanto non esiste un distruttore. Non hanno il controllo su di te impostando una variabile su niente per poi smaltire lì oggetti o contenuti che richiedono lo smaltimento. – OneFineDay

+0

Certo, per Process.GetProcesses() puoi mantenere un array interno di tutti gli oggetti Process() che hai mai restituito ai chiamanti e quindi controllare periodicamente se sei l'unico che ha un riferimento all'oggetto e se è così Dispose() – Denis

+3

@Denis Determinare se qualcun altro ha un riferimento ad esso non è qualcosa che puoi effettivamente fare. – Servy

risposta

7

Non esiste una regola generale. Dipenderà dalla situazione e dal modo in cui il metodo in questione è stato progettato, dal fatto che "tu" sia responsabile o meno dello smaltimento degli oggetti a cui hai accesso. È qui che la documentazione è spesso importante per aiutare gli utenti del tipo a comprendere le proprie responsabilità.

ho sempre pensato che fosse fardello del creatore di Dispose()

Questo non può essere del tutto vero. A volte accade che un oggetto usa e getta sopravviva per tutta la durata del blocco di codice che lo crea. Mentre è il più semplice quando il creatore può smaltire l'oggetto, a volte è semplicemente impossibile per loro essere in grado di farlo. Quando restituire un oggetto usa e getta da un metodo è una situazione in cui spesso non è possibile che il codice che crea l'oggetto usa e getta lo pulisca, poiché è necessario che la vita sia più piccola di rispetto alla durata dell'oggetto monouso.

+0

Posso creare un oggetto usa e getta istanziando uno all'interno della dichiarazione di un blocco using. Un blocco usando non sarebbe esattamente ciò che risolve questo? La durata della chiamata al metodo che crea l'oggetto usa e getta è inferiore all'oggetto monouso effettivo stesso ...? Se questo non è il caso e mi manca il punto, potrei convincerti ad aggiungere un esempio (anche un artificio) alla tua risposta? –

+0

Accidenti, non leggo la documentazione attentamente per ogni classe che uso. Sei sicuro che non ci sia una regola? – Denis

+0

@Denis, no non esiste una regola per questa situazione. Dovresti decidere da solo. – VMAtm

0

La regola è molto semplice: se pensi che altri programmi utilizzeranno il tuo IDisposables, non distruggili. Altrimenti, fallo.

Ad esempio: GetProcesses() restituisce altri processi che sono potenzialmente utilizzati da altri programmi, quindi non è necessario smaltire.

Dall'altro lato, i file che hai aperto dovrebbero essere rilasciati per altri processi di sistema operativo, così si dovrebbe chiudere e smaltire i flussi di wrapper sopra di loro (ad esempio, si dovrebbe smaltire vapore restituito dal File.Open metodo).

Aggiornamento:
From MSDN:

  • DO implementare il modello di base Dispose su tipi contenenti istanze di tipi usa e getta. Vedere la sezione Schema di smaltimento di base per i dettagli sul motivo di base. Se un tipo è responsabile della durata di di altri oggetti usa e getta, gli sviluppatori hanno bisogno di un modo per disporre anche di . Utilizzare il metodo Dispose del contenitore è un modo conveniente per rendere possibile ciò .
    • DO implementare il modello di base Smaltire e forniscono un finalizzatore sui tipi in possesso di risorse che devono essere liberato in modo esplicito e che non hanno finalizzatori.
      Ad esempio, il modello deve essere implementato sui tipi che memorizzano i buffer di memoria non gestiti. La sezione Tipi finalizzabili illustra le linee guida relative a implementando i finalizzatori.
    • CONSIDER implementare il modello di dispersione di base su classi che a loro volta non contengono risorse non gestite o oggetti usa e getta ma probabilmente hanno sottotipi che lo fanno.
+0

ma se non li distruggo, lascio maniglie in giro ... Quindi dovrei distruggerli? Pensi che gli oggetti Process() che vengono restituiti siano condivisi. Scommetto che sono appena creati per ogni richiesta a Process.GetProcesses() e se non lo hai fatto, probabilmente avresti una perdita di handle ... – Denis

+0

Processi - no, non dovresti (se non li stai creando) . Immagini o file o altre cose del genere - sì, dovresti. – VMAtm

+0

"Lascio gli handle fluttuanti" - saranno finalizzati quindi è ok – Vlad

1

Con relativamente poche eccezioni (la maggior parte delle quali potrebbero essere descritte come approcci meno pericolosi per gestire un codice mal progettato che non può essere modificato), ogni istanza di IDisposable dovrebbe in ogni momento avere esattamente una proprietario ben definito. Nei casi in cui un metodo restituisce qualcosa di un tipo che implementa IDisposable, il contratto per il metodo specificherà se il metodo sta cedendo la proprietà (nel qual caso il chiamante dovrebbe accertarsi che l'oggetto venga eliminato - eliminando l'oggetto stesso o cedendo la proprietà a qualcun altro) o se il metodo sta semplicemente restituendo un riferimento a un oggetto di proprietà di qualcun altro.

In codice correttamente scritto, la questione se un oggetto debba o meno essere smaltito è raramente una chiamata di giudizio. Il proprietario di un oggetto dovrebbe assicurarsi che venga eliminato; nessun altro dovrebbe disporlo. Occasionalmente può essere necessario che un metodo accetti un parametro che indica se il metodo deve trasferire la proprietà di uno IDisposable. Ad esempio, se il codice vuole creare un suono, passarlo a un metodo "avvia la riproduzione del suono" e non vuole più occuparsi di quel suono, potrebbe essere più comodo avere il codice per riprodurre il suono accetta e dispose il suono quando è fatto; se il codice vuole essere in grado di riprodurre un suono ripetutamente, tuttavia, e farà in modo che l'oggetto sonoro rimanga attivo fino a quando è necessario, sarebbe più conveniente per il codice di riproduzione audio non assumere la proprietà. L'utilizzo di metodi separati può in qualche modo essere più pulito, ma l'utilizzo di un parametro può facilitare l'incapsulamento.

In genere, quando il codice restituisce un elenco di oggetti che implementano IDisposable, lo scopo del codice è quello di identificare oggetti senza trasmettere alcun interesse di proprietà in loro. In assenza di un interesse di proprietà, il codice che riceve tale lista dovrebbe non chiamare Dispose su di esso.

Problemi correlati