2010-06-30 17 views
10

Sto facendo uno sviluppo di ASP.NET in VS e ho appena trovato un piccolo suggerimento di codice interessante (penso che provengano da coderush ma potrei sbagliarmi).Perché dovrei chiamare dispose sui controlli ASP.NET?

Ogni volta che creo i controlli, mi viene indicato che dovrei usare un'istruzione "using" per loro. Sono un po 'confuso su quello che sta succedendo qui però. con l'usando il mio codice è qualcosa di simile:

using (HtmlTableRow tableRow = new HtmlTableRow()) 
{ 
    tableRow.Attributes.Add("class", isOddRow ? "OddRow" : "EvenRow"); 
    listingTable.Rows.Add(tableRow); 
    addCell(tableRow, row, "issueId"); 
    addCell(tableRow, row, "Title"); 
    addCell(tableRow, row, "Type"); 
    addCell(tableRow, row, "Summary"); 
} 

Quindi mi aspetto che alla fine l'istruzione using sarà chiamata smaltire sul TableRow. Tuttavia, i documenti nella libreria MSDN dicono:

Il metodo Dispose lascia il controllo in uno stato inutilizzabile. Dopo aver chiamato il metodo , è necessario rilasciare tutti i riferimenti al controllo in modo che la memoria occupata possa essere reclamata dalla procedura di garbage collection.

Quindi mi aspetto che ora ho un oggetto inutilizzabile nella mia struttura di controllo in modo che si spezzerebbe o no il rendering o qualcosa del genere. Tuttavia, tutto sembra funzionare bene.

Quindi quello che mi chiedo è perché tutti i controlli sono monouso? È solo perché alcuni di essi saranno e rendendoli tutti usa e getta significa che una chiamata a disporre al livello più alto può essere passata a tutti i controlli figlio in modo ricorsivo?

Penso che capirei se non fosse il fatto che i documenti affermano esplicitamente che lo smaltimento di un controllo lo rende inutilizzabile ... I documenti sono semplicemente sbagliati?

+0

Come possiamo gestire gli oggetti orfani (che @Toby menzionato) se non stiamo usando il blocco "using"? – Lijo

risposta

14

Non dovresti farlo. Quello che devi fare è assicurarti che listTable si trovi nella collezione Controls in modo che venga eliminata quando la Pagina viene eliminata. L'oggetto listTable è quindi responsabile del corretto smaltimento di tutti i suoi figli.

Ecco perché tutti gli oggetti Control implementano l'interfaccia IDisposable. In questo modo, ogni controllo genitore può chiamare Dispose su tutti i suoi figli senza dover prima testare/trasmettere ciascuno di essi. Ogni controllo è individualmente responsabile per determinare se effettivamente ha qualcosa che deve essere ripulito quando viene chiamato il suo metodo Dispose.

I documenti non sono sbagliati. Qualsiasi oggetto debitamente scritto che implementa IDisposable e contiene dati di stato effettivamente ripuliti durante il processo di smaltimento devono generare un'eccezione ObjectDisposedException se si accede a una delle sue proprietà o metodi pubblici/protetti/interni dopo che è stata eliminata. (Si suppone che lo stato non valido dopo Dispose sia stato chiamato.) Alcuni tipi ignoreranno questa regola se in realtà non hanno nulla da pulire e non devono preoccuparsi dello stato non valido.

Il motivo che stai ricevendo un suggerimento per avvolgerlo in un blocco using è perché l'analizzatore non si rende conto che listingTable disporrà la sua collezione Rows, che disporrà ognuno degli oggetti riga che sono stati aggiunti ad esso. Inoltre, se viene generata un'eccezione tra HtmlTableRow tableRow = new HtmlTableRow() e listingTable.Rows.Add(tableRow), l'oggetto HtmlTableRow sarà "orfano" e non sarà nella gerarchia IDisposable di nessun altro oggetto. Code Analysis vuole che tu usi un blocco try/finally per eliminare immediatamente lo HtmlTableRow se questo accade.

+1

Grazie. Ho avuto un sospetto su gran parte di questo, ma è bello avere un po 'più di dettaglio su quello che sta succedendo qui. Non avevo nemmeno considerato l'orfano del controllo. – Chris

+0

Come possiamo gestire gli oggetti 'orfani' se non stiamo usando il blocco" using "? – Lijo

+0

@Lijo: usa un blocco try/finally – Toby

Problemi correlati