Quando dovrei usare i blocchi “using” in C #?

Ci sono casi particolari in cui dovrei (o non dovrei?) Usare i blocchi “using”:

using(SomeType t = new SomeType()){ ... } 

    Quando la class SomeType implementa IDisposable .

    Alcuni oggetti richiedono un’azione da intraprendere quando hai finito con loro. Di solito questo è dovuto al fatto che l’object utilizza una sorta di risorsa che deve essere smaltita. Ad esempio, se si dispone di un object file di un file di class e questo object apre un file dal file system, sarà necessario chiudere nuovamente il file nel file system.

    Se si è appena uscito dall’object file e si è dimenticato di chiamare file.Close (), non verrà ripulito fino a quando non viene eseguito il Garbage Collector (GC) e non si è ancora verificato l’utilizzo dell’object file. Quando si esegue il Garbage Collector, è necessario lasciare il Common Language Runtime (CLR) per decidere. Se il GC non viene eseguito per un po ‘di tempo dopo aver terminato con il file, il file potrebbe rimanere aperto potenzialmente per un lungo periodo di tempo. Questo può rappresentare un grosso problema se ci sono molti oggetti file, o se qualcosa vuole aprire un file, ma non può farlo perché l’object file che hai lasciato è ancora in agguato.

    Per risolvere questo problema, C # ha l’interfaccia IDisposable. Questo ha un metodo chiamato Dispose. Le classi che richiedono un po ‘di pulizia implementano questo metodo Dispose. Questo ti dà un modo standard per ripulire qualsiasi object che usi risorse. Ci sono un sacco di classi che devono essere chiamate Dispose. Il problema con questo è che il codice viene coperto con le chiamate a Dispose, e sono difficili da seguire perché il luogo in cui hai new’ed l’object e chiama Dispose per pulirlo sono diversi. Quindi, hai dovuto controllare molto il codice ed essere molto attento a verificare che ci fossero chiamate per Smaltire nel posto giusto.

    Per risolvere questo problema, C # ha introdotto la parola chiave ‘using’. Puoi mettere una parola chiave ‘using’ nella posizione in cui tu nuovo un object, e questo garantisce che Dispose verrà richiamato per te. Garantisce che Dispose sarà chiamato qualunque cosa accada … anche se c’è un’eccezione generata nel corpo dell’istruzione using.

    Quindi, dovresti usare ‘using’ quando vuoi essere sicuro che un object che assegna le risorse verrà ripulito.


    l’utilizzo può essere utilizzato solo per oggetti dichiarati in pila, ovvero in una funzione. Non funziona per oggetti dichiarati come membri di una class. Per loro, devi chiamare Dispose te stesso. Potrebbe essere necessario implementare Dispose nella class in modo che possa chiamare Dispose su qualsiasi object membro che lo richiede.


    Gli oggetti comuni che devono essere utilizzati su di essi sono: file, connessioni database, oggetti grafici come penna e pennello.


    A volte viene utilizzato anche quando si desidera che due operazioni avvengano insieme. Ad esempio, se vuoi scrivere una dichiarazione di log quando viene inserito un blocco di codice e quando esce potresti scrivere una class di log che potresti usare in questo modo:

     using( Log log = new Log("Doing stuff") ) { // Stuff } 

    Il costruttore della class di log può essere creato per scrivere il messaggio e anche il metodo Dispose potrebbe scriverlo. Implementare il finalizzatore (~ Log) per verificare se il metodo Dispose non viene chiamato per assicurarsi che l”uso’ venga ricordato attorno al ‘nuovo registro’.

    Utilizzare l’ using ogni volta che il tipo implementa IDisposable , a meno che non lo si avvolga in un blocco try / catch ogni caso, quindi si potrebbe anche (a seconda del look che si preferisce) utilizzare un blocco finally .

    Vedo molte altre risposte indicate quando dovresti avere una dichiarazione using . Voglio indirizzare quando in particolare non dovrei avere una dichiarazione using :

    Se è necessario utilizzare l’object al di fuori dell’ambito della funzione corrente, non using un blocco. Un buon esempio è un metodo factory che restituisce una connessione al database o un metodo che deve restituire un datareader. In entrambi i casi, se crei il tuo object con un’istruzione using , verrebbe eliminato prima del metodo restituito e quindi non utilizzabile al di fuori del metodo.

    Ora, vuoi comunque essere sicuro che quegli oggetti siano disposti, quindi potresti ancora voler using un’istruzione da qualche parte. Basta non includerlo nel metodo in cui viene effettivamente creato l’object. Invece, puoi racchiudere la chiamata alla funzione stessa in un’istruzione using .

    Quando SomeType implementa IDisposable.

    Questo è un indizio per te dello sviluppatore che SomeType utilizza risorse non gestite che devono essere ripulite.

    Esempio:

      using(SqlConnection MyConnection = new SqlConnection("Connection string")) { MyConnection.Open(); //... // 1. SQLConnection is a type that implements IDisposable // 2. So you can use MyConnection in a using statement // 3. When using block finishes, it calls Dispose method of // SqlConnection class // 4. In this case, it will probably close the connection to // the database and dispose MyConnection object } 

    Puoi creare i tuoi oggetti che implementano IDisposable:

     public class MyOwnObjectThatImplementsIDisposable : IDisposable { //... some code public void Dispose() { // Put here the code you want to be executed when the // using statement finish. } } 

    Quindi potresti usare un object di MyOwnObjectThanImplementsIDisposable type in un’istruzione using:

      using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable) { // When the statement finishes, it calls the // code you´ve writed in Dispose method // of MyOwnObjectThatImplementsIDisposable class } 

    Spero che questo ti aiuti

    In questo contesto l’istruzione using è utile per i tipi che implementano IDisposable. Quando il blocco di codice esce dall’ambito Dispose() using , Dispose() viene chiamato implicitamente. È una buona abitudine quando si lavora con oggetti che si desidera smaltire immediatamente dopo l’uso.

    Un’istanza specifica in cui è necessario prestare attenzione utilizzando un blocco using è un client di servizio WCF .

    Come notato in questo articolo di MSDN , il wrapping di un client WCF (che implementa IDisposable ) in un blocco using potrebbe mascherare qualsiasi errore che si traduce nel lasciare il client in uno stato di errore (come un timeout o un problema di comunicazione). Per farla breve, quando viene chiamato Dispose() , il metodo Close() del client si triggers, ma genera ed errore perché è in uno stato di errore. L’eccezione originale viene quindi mascherata dalla seconda eccezione. Non bene.

    Esistono varie soluzioni alternative, inclusa una nell’articolo MSDN stesso. Altre possono essere trovate su IServiceOriented e blog.davidbarret.net .

    Preferisco l’ultimo metodo, me stesso.

    Se si desidera una regola di riepilogo. Ogni volta che un object utilizza IDisposable in cui non si avrebbe una presa, utilizzare l’uso. L’uso, in sostanza, è questo schema:

     try { //instantiate and use object } finally { //dispose object } 

    Se non hai bisogno di una presa, l’utilizzo può farti risparmiare la digitazione, che è una buona cosa.

    La regola principale è: * Utilizzare la dichiarazione USING quando gli oggetti implementano l’interfaccia IDisposable.

    Questa interfaccia fornisce il metodo Dispose, che dovrebbe rilasciare le risorse dell’object. Se questo metodo non viene invocato, l’object rimarrà in memoria fino a quando CLR vuole eseguire la garbage collection. Se il programmatore utilizza l’istruzione USING, alla fine l’object verrà eliminato e tutte le risorse saranno libere.

    È molto importante che tutte le risorse che non sono più in uso siano gratuite il prima ansible.

    Per maggiori informazioni basta visitare questo link: microsoft

    Forse vale la pena ricordare che la ragione sottostante per l’aggiunta di “using” lo sta per “languge”: alcune risorse possono essere scarse abbastanza da non avere senso aspettare che GC chiami IDisposable. Ad esempio, connessioni DB. Se usi try / catch / finally non finirai con una connessione ciondolante, ma la connessione rimarrà sospesa fino a quando GC non eseguirà il kick in e questo potrebbe richiedere del tempo (se non lo chiudi esplicitamente). Se usi “using” (scusa il gioco di parole) rilascerai immediatamente la connessione anche se hai dimenticato di chiuderla e anche se si è verificata qualche eccezione all’interno del blocco using.
    Un altro motivo, come accennato nel post precedente, è che i programmatori non sempre usano finalmente per ripulire. Se non si utilizza infine nel caso di eccezione si finisce con perdite di risorse …

    Una situazione è quando vuoi fare qualcosa all’inizio di un blocco di codice, e poi annullarlo alla fine del blocco, incondizionatamente (anche se c’è un lancio).

    Il Ctor per la class usa e getta che si crea (e chiama all’interno dell’utilizzo) eseguirà l’azione, e quindi il metodo Dispose annullerebbe quell’azione. Questo è in genere il modo in cui lo uso.

    Altre persone hanno già parlato di “IDisposable”.

    Ma una delle avvertenze quando si usa la frase “using” è che, qualsiasi eccezione lanciata all’interno di “using” non verrà catturata anche se si pensa che “SomeType” sarà disposto indipendentemente.

    Quindi nel seguente frammento,

     using (SomeType t = new SomeType()){ throw new Exception("thrown within using"); } 

    throw new Exception("thrown within using"); non dovrebbe essere ignorato.

    Vorrei anche aggiungere che usare un’istruzione using() se qualcosa implementa IDispose e anche se quel qualcosa che si desidera eliminare rimane su risorse NON-MANAGED come le connessioni al database e gli handle di file.

    Se si tratta di un object normale con say List , dove T è come un object Customer che contiene nomi e indirizzi, non è necessario. Il garbage collector è abbastanza intelligente per gestirlo per te. Ma il garbage collector NON restituirà le connessioni al pool di connessioni o gli handle di file chiusi.