Qual è il modo corretto di disporre di un nuovo modulo senza che si chiuda immediatamente?

Pertanto, nelle mie app, tendo a creare nuove istanze di moduli al volo, quindi utilizzare Form.Show () per visualizzarli (non modali).

private void test_click(object sender, EventArgs e) { var form = new myForm(); form.Show(); } 

Tuttavia, Code Cracker mi dice che questi moduli dovrebbero essere smaltiti. Quindi, li ho avvolti con l’istruzione “using”, ma poi si chiudono subito dopo l’apertura.

 using (var form = new myForm()) { form.Show(); } 

Non voglio usare Form.ShowDialog (), perché in alcuni casi sto aprendo nuove windows che mostrano solo i report; Non ho bisogno che siano modali.

Hmm, “code cracker” sembra essere un termine molto appropriato per quello strumento, il suo consiglio sicuramente ti ha fatto scrivere un codice che rompe il tuo programma. La regola d’oro è di non fidarsi mai dei consigli identificabili da uno strumento di analisi del codice statico, nessuno di questi ha mai una visione sufficiente dell’esecuzione del codice. Non riescono mai a capire quale chiamata Dispose () abbia completato il lavoro.

Quello che non può vedere è che la class Form sa già come disporsi. È molto facile farlo, l’object diventa inutilizzabile quando la finestra si chiude. Quando non ci sono più windows, non c’è motivo di continuare a utilizzare l’object Form. Un lusso che non è altrimenti molto comune in .NET ma sicuramente ispirato a programmatori molto intelligenti che hanno funzionato per Xerox 45 anni fa.

C’è solo una regola speciale che devi tenere a mente, non si dispone da sola quando usi ShowDialog () per visualizzare la finestra. Questo è stato intenzionale, rende il recupero dei risultati della finestra di dialogo troppo rischioso. L’ utilizzo dell’istruzione using per una chiamata ShowDialog () è molto semplice, la chiamata non ritorna finché la finestra non viene chiusa.

Devo smaltire un modulo dopo che il modulo è stato chiuso?

Quando si chiude un Form , un messaggio WM_CLOSE verrà inviato alla finestra. Se WmClose un’occhiata al codice sorgente del metodo WmClose che gestisce il messaggio WM_CLOSE , vedrete:

  • Per i moduli modali (che hai mostrato usando ShowDialog ), il metodo Dispose non verrà chiamato e il modulo esiste dopo la chiusura ed è ansible utilizzare le sue proprietà per ottenere alcuni dati o mostrarli di nuovo.

  • Per i moduli non modali (che hai mostrato usando Show ), dopo che il modulo è stato chiuso, verrà chiamato il metodo Dispose .

Quindi ecco la conclusione:

  • Quando mostri un modulo utilizzando il metodo Show non è necessario (e non puoi) chiamare Dispose . Il modulo verrà smaltito automaticamente dopo essere stato chiuso.

  • Quando mostri un modulo usando ShowDialog devi chiamare Dispose manualmente. Una buona pratica è usare le forms modali in un blocco using .

Potresti implementare qualche tipo di gestore di moduli che sottoscriverà l’ OnFormClosedEvent per ogni modulo che mostra, potrà quindi eliminarli … qualcosa come:

 public class FormManager { public T ShowForm() where T : Form, new() { var t = new T(); t.OnFormClosing += DisposeForm; return t; } void DisposeForm(object sender, FormClosedEventArgs args) { ((Form)sender).Dispose(); } } 

Potresti anche arrivare a implementare IDisposable e disporre tutti i moduli non disposti quando il gestore è disposto 🙂

Pertanto, in base alla risposta su MSDN , i moduli non modali vengono automaticamente eliminati ogni volta che vengono chiusi.

Ho deciso di testare questo aprendo il mio modulo di prova più volte e chiudendoli. Ho persino aperto più istanze allo stesso tempo. Dopo un secondo o due, la memoria utilizzata da queste forms è stata recuperata, il che indicherebbe che erano state smaltite correttamente.