2012-01-09 12 views
5

Quando si crea una maschera o un controllo utente, il progettista WinForms genera un metodo dispose che assomiglia a questo:Perché il progettista WinForms genera un codice un po '"scomodo" nel suo metodo di smaltimento?

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

Il problema con questo codice è che può portare a un comportamento errato se è mai modificato per smaltire oggetti aggiuntivi. Ho visto i file .designer.cs con METODI DI SMALTIMENTO che assomigliano a questo:

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
      if (_myDisposable != null) 
       _myDisposable.Dispose(); 
      if (_myOtherDisposable != null) 
       _myOtherDisposable.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

... che non è corretto, in quanto lo smaltimento dei _myDisposable e _myOtherDisposable non dovrebbe dipendere o meno di componenti è nullo.

Quindi, ignorando l'argomento sull'opportunità o meno di modificare questo codice generato dal designer e ignorando il fatto che è possibile modificarlo modificando i modelli, la mia domanda è: perché il progettista non genera codice sembra più questo?

protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if(components != null) 
       components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

Questo codice ha lo stesso risultato finale, ma è più sicuro e meno soggetto a errori durante la modifica.

+0

Il primo e il terzo blocco di codice sono (quasi) uguali. O mi sta sfuggendo qualcosa? –

+0

@Erno - Hai ragione, dal momento che '&&' andrà in cortocircuito. – Oded

+0

Quindi non c'è dubbio (cucchiaio)? –

risposta

4

La risposta è: perché la vostra convenienza non era la preoccupazione principale di chi ha scritto questa funzione in Microsoft. O forse pensavano che tu, essendo un dipendente non-Microsoft, non possa essere un buon programmatore, quindi, probabilmente dovresti stare lontano dalle attività rischiose come modificare il metodo Dispose() di un oggetto.

A proposito, il metodo Dispose() si trova al di fuori dell'area all'interno del file .Designer.cs che è designato come "non modificare questo codice generato dal designer", quindi suppongo che sia corretto modificarlo.

1

Hai ragione soprattutto, e non hai nemmeno menzionato il fatto che è inserito nel file Designer.cs.

Dovrai prima spostarlo (in MyForm.cs) e quindi modificarlo. Con un po 'di buon senso ...

Ma è in gran parte accademico, componenti == null sarà vero solo su un modulo completamente vuoto. Rilascia 1 pulsante o etichetta e il problema non si presenta.

Ho appena controllato, anche su un modulo vuoto non è null. (OK, solo per Fx 4+ a quanto pare)

+0

I componenti non sembrano mai nulli in VS 2010, ma in VS 2008 e sotto sarà sempre nullo a meno che non si aggiunga specificamente un componente come un timer al modulo. –

1

Il modo consigliato di gestire lo smaltimento di risorse contenute in un modulo consiste nell'utilizzare gli eventi FormClosing o FormClosed. UserControl ha un evento Disposed per lo stesso scopo.

+0

Chiusura e Chiusura sono entrambi obsoleti, sostituiti da FormClosing e FormClosed in .NET 2.0. Dove hai trovato questa raccomandazione? –

+0

@Hans, ho modificato la risposta di conseguenza; Mi è stato detto verbalmente qualche anno fa di usare Closing/Closed e ho dimenticato che in realtà si chiamavano FormClosing e FormClosed. In realtà non sapevo che esistessero eventi obsoleti con altri nomi. –

3

Direi che questo è dovuto al fatto che lo schema "ufficiale" di Microsoft IDisposable tenta di soddisfare troppe situazioni, inutilmente.

Per ulteriori dettagli, vedere questo eccellente articolo di Stephen Cleary: What your mother never told you about IDisposable. Ha alcune informazioni dettagliate sui problemi con IDisposable e su come risolverli.

Stephen offre una semplice linea guida: non combinare le risorse gestite e non gestite in un'unica classe; invece, avvolgere tutte le risorse non gestite in una classe IDisposable il cui unico scopo è quello di eliminare la risorsa non gestita.

Se si segue questa linea guida, tali metodi arcani Dispose cessano di essere necessari, allo stesso tempo risolvono un sacco di altri problemi più gravi con il modello consigliato da Microsoft.

+0

+1. Anche così, dopo averli racchiusi in IDisposable è ancora necessario invocare 'Dispose()' quando hai finito con loro, esplicitamente o tramite 'using() {}'. Altrimenti il ​​comportamento non è molto meglio di non averli affatto avvolti. – JMD

Problemi correlati