it-swarm.it

Quali sono gli usi di "usare" in C #

Utente kokos ha risposto alla meravigliosa Caratteristica nascosta di C # domanda menzionando using parola chiave. Puoi approfondire questo? Quali sono gli usi di using?

289
ubermonkey

La ragione dell'istruzione using è garantire che l'oggetto sia eliminato non appena esce dall'ambito e non richiede codice esplicito per garantire che ciò avvenga.

Come in Comprensione dell'istruzione 'using' in C #, il .NET CLR converte

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

a

{ // Limits scope of myRes
    MyResource myRes= new MyResource();
    try
    {
        myRes.DoSomething();
    }
    finally
    {
        // Check for a null resource.
        if (myRes != null)
            // Call the object's Dispose method.
            ((IDisposable)myRes).Dispose();
    }
}
440
paulwhit

Dal momento che molte persone continuano a fare:

using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
   //code
}

Immagino che molte persone ancora non sappiano che puoi fare:

using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
   //code
}
121
BlackTigerX

Cose del genere:

using (var conn = new SqlConnection("connection string"))
{
   conn.Open();

    // Execute SQL statement here on the connection you created
}

Questo SqlConnection verrà chiuso senza la necessità di chiamare esplicitamente la funzione .Close(), e ciò avverrà anche se viene generata un'eccezione , senza la necessità di un try/catch/finally.

95
Joel Coehoorn

utilizzando può essere utilizzato per chiamare IDisposable. Può anche essere usato per tipi di alias.

using (SqlConnection cnn = new SqlConnection()) { /*code*/}
using f1 = System.Windows.Forms.Form;
30
MagicKat

usando, nel senso di

using (var foo = new Bar())
{
  Baz();
}

In realtà è una scorciatoia per un blocco try/finally. È equivalente al codice:

var foo = new Bar();
try
{
  Baz();
}
finally
{
  foo.Dispose();
}

Ovviamente, noterai che il primo frammento di codice è molto più conciso del secondo e che ci sono molti tipi di cose che potresti voler fare come pulizia anche se viene lanciata un'eccezione. Per questo motivo, abbiamo creato una classe che chiamiamo Scope che consente di eseguire codice arbitrario nel metodo Dispose. Ad esempio, se hai una proprietà denominata IsWorking che avresti sempre voluto impostare su false dopo aver tentato di eseguire un'operazione, dovresti farlo in questo modo:

using (new Scope(() => IsWorking = false))
{
  IsWorking = true;
  MundaneYetDangerousWork();
}

Puoi leggere di più sulla nostra soluzione e su come la abbiamo derivata qui .

21
David Mitchell

La documentazione Microsoft afferma che usando ha una doppia funzione ( https://msdn.Microsoft.com/en-us/library/zhdeatwt.aspx ), sia come direttiva che in dichiarazioni . Come una dichiarazione , come è stato sottolineato qui in altre risposte, la parola chiave è fondamentalmente zucchero sintattico per determinare un ambito di disposizione di un IDisposable oggetto. Come una direttiva , viene abitualmente utilizzata per importare spazi dei nomi e tipi. Inoltre, come direttiva, puoi creare alias per namespace e tipi, come indicato nel libro "C # 5.0 In poche parole: la guida definitiva" ( http://www.Amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8 ), di Joseph e Ben Albahari. Un esempio:

namespace HelloWorld
{
    using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
    public class Startup
    {
        public static AppFunc OrderEvents() 
        {
            AppFunc appFunc = (IDictionary<DateTime, string> events) =>
            {
                if ((events != null) && (events.Count > 0))
                {
                    List<string> result = events.OrderBy(ev => ev.Key)
                        .Select(ev => ev.Value)
                        .ToList();
                    return result;
                }
                throw new ArgumentException("Event dictionary is null or empty.");
            };
            return appFunc;
        }
    }
}

Questo è qualcosa da adottare con saggezza, dal momento che l'abuso di questa pratica può danneggiare la chiarezza del proprio codice. C'è una bella spiegazione sugli alias C #, menzionando anche pro e contro, in DotNetPearls ( http://www.dotnetperls.com/using-alias ) .

10

L'ho usato molto in passato per lavorare con flussi di input e output. Puoi nidificarli in modo corretto e toglie molti dei potenziali problemi in cui ti imbatti di solito (chiamando automaticamente dispose). Per esempio:

        using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
        {
            using (BufferedStream bs = new BufferedStream(fs))
            {
                using (System.IO.StreamReader sr = new StreamReader(bs))
                {
                    string output = sr.ReadToEnd();
                }
            }
        }
10
Sam Schutte

Aggiungendo solo un piccolo qualcosa che mi ha sorpreso non è venuto fuori. La caratteristica più interessante dell'uso (secondo me) è che non importa come si esce dall'utilizzo del blocco, esso disporrà sempre dell'oggetto. Ciò include resi ed eccezioni.

using (var db = new DbContext())
{
    if(db.State == State.Closed) throw new Exception("Database connection is closed.");
    return db.Something.ToList();
}

Non importa se l'eccezione viene lanciata o la lista viene restituita. L'oggetto DbContext sarà sempre eliminato.

8
Pluc

Un altro grande uso dell'uso è quando si crea un'istanza di una finestra di dialogo modale.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using
6
Lucas

In conclusione, quando si utilizza una variabile locale di un tipo che implementa IDisposablename__, sempre , senza eccezioni, utilizzare usingname__1.

Se si usano variabili IDisposablenon locali, allora sempre implementa il modello IDisposableNAME_ .

Due semplici regole, nessuna eccezione1. Prevenire le perdite di risorse altrimenti è un vero dolore per * ss.


1): L'unica eccezione è: quando si gestiscono le eccezioni. Potrebbe quindi essere meno codice per chiamare Disposeesplicitamente nel blocco finallyname__.

5
Konrad Rudolph

È possibile utilizzare lo spazio dei nomi alias tramite l'esempio seguente:

using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;

Questo è chiamato a usando la direttiva alias come puoi vedere, può essere usato per nascondere riferimenti prolissi se vuoi renderlo evidente nel tuo codice a cui ti riferisci ad esempio.

LegacyEntities.Account

invece di

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

o semplicemente

Account   // It is not obvious this is a legacy entity
4
VictorySaber

È interessante notare che è anche possibile utilizzare il modello usando/IDisposable per altre cose interessanti (come l'altro punto nel modo in cui Rhino Mocks lo usa). Fondamentalmente, puoi approfittare del fatto che il compilatore sempre chiama .Dispose sull'oggetto "used". Se hai qualcosa che deve succedere dopo una certa operazione ... qualcosa che ha un inizio e una fine definiti ... allora puoi semplicemente creare una classe IDisposable che avvia l'operazione nel costruttore, e quindi finisce nel metodo Dispose.

Questo ti permette di usare veramente la sintassi usando per denotare l'inizio e la fine espliciti di detta operazione. Questo è anche il modo in cui funziona la roba di System.Transactions.

4
Joel Martinez
public class ClassA:IDisposable

{
   #region IDisposable Members        
    public void Dispose()
    {            
        GC.SuppressFinalize(this);
    }
    #endregion
}

public void fn_Data()

    {
     using (ClassA ObjectName = new ClassA())
            {
                //use objectName 
            }
    }
3
Shiraj Momin

Quando si utilizza ADO.NET è possibile utilizzare il lavoro di chiavi per cose come l'oggetto di connessione o l'oggetto lettore. In questo modo, una volta completato il blocco di codice, la connessione verrà automaticamente eliminata.

3
Joseph Daigle

"using" può anche essere usato per risolvere i conflitti di spazio dei nomi. Vedi http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ per un breve tutorial che ho scritto sull'argomento .

3
David Arno

L'istruzione using dice a .NET di rilasciare l'oggetto specificato nel blocco using quando non è più necessario. Quindi dovresti usare il blocco 'using' per le classi che richiedono la pulizia dopo di loro, come i Tipi System.IO.

1

Ci sono due modi per utilizzare la parola chiave in C # come segue.

  1. come una direttiva

Generalmente utilizziamo la parola chiave using per aggiungere spazi dei nomi nei file code-behind e di classe. Quindi rende disponibili tutte le classi, le interfacce e le classi astratte e i loro metodi e proprietà nella pagina corrente.

Ex:

using System.IO;  
  1. come una dichiarazione

Questo è un altro modo di usare la parola chiave using in C #. Svolge un ruolo fondamentale nel migliorare le prestazioni in Garbage Collection. L'istruzione using assicura che venga chiamato Dispose () anche se si verifica un'eccezione quando si creano oggetti e si chiamano metodi, proprietà e così via. Dispose () è un metodo presente nell'interfaccia IDisposable che consente di implementare Garbage Collection personalizzata. In altre parole, se sto facendo qualche operazione di database (Insert, Update, Delete) ma in qualche modo si verifica un'eccezione, qui l'istruzione using chiude automaticamente la connessione. Non è necessario chiamare esplicitamente il metodo Close () della connessione.

Un altro fattore importante è che aiuta nel pool di connessioni. Il pool di connessioni in .NET aiuta a eliminare la chiusura di una connessione di database più volte. Invia l'oggetto di connessione a un pool per uso futuro (prossima chiamata al database). La prossima volta che viene chiamata una connessione al database dall'applicazione, il pool di connessioni recupera gli oggetti disponibili nel pool. Quindi aiuta a migliorare le prestazioni dell'applicazione. Quindi, quando usiamo l'istruzione using, il controller invia l'oggetto al pool di connessioni automaticamente, non è necessario chiamare esplicitamente i metodi Close () e Dispose ().

Puoi fare lo stesso come l'istruzione using usando il blocco try-catch e chiamare esplicitamente il Dispose () all'interno del blocco finally. Ma l'istruzione using fa automaticamente le chiamate per rendere il codice più pulito e più elegante. All'interno del blocco using, l'oggetto è di sola lettura e non può essere modificato o riassegnato.

Ex:

    string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";  

using (SqlConnection conn = new SqlConnection(connString))  
{  
      SqlCommand cmd = conn.CreateCommand();  
      cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";  
      conn.Open();  
      using (SqlDataReader dr = cmd.ExecuteReader())  
      {  
         while (dr.Read())  
         Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));  
      }  
}  

Nel codice precedente non sto chiudendo alcuna connessione, si chiuderà automaticamente. L'istruzione using chiamerà conn.Close () automaticamente a causa dell'istruzione using (utilizzando (SqlConnection conn = new SqlConnection (connString)) e lo stesso per un oggetto SqlDataReader e anche se si verifica un'eccezione, la connessione verrà chiusa automaticamente.

Per maggiori informazioni -> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

1

Per me il nome "using" è un po 'confuso, perché può essere una direttiva per importare un Namespace o un'istruzione (come quella discussa qui) per la gestione degli errori.

Un nome diverso per la gestione degli errori sarebbe stato bello, e forse in qualche modo più ovvio.

1
Seb

Può anche essere usato per creare ambiti per Esempio:

class LoggerScope:IDisposable {
   static ThreadLocal<LoggerScope> threadScope = 
        new ThreadLocal<LoggerScope>();
   private LoggerScope previous;

   public static LoggerScope Current=> threadScope.Value;

   public bool WithTime{get;}

   public LoggerScope(bool withTime){
       previous = threadScope.Value;
       threadScope.Value = this;
       WithTime=withTime;
   }

   public void Dispose(){
       threadScope.Value = previous;
   }
}


class Program {
   public static void Main(params string[] args){
       new Program().Run();
   }

   public void Run(){
      log("something happend!");
      using(new LoggerScope(false)){
          log("the quick brown fox jumps over the lazy dog!");
          using(new LoggerScope(true)){
              log("nested scope!");
          }
      }
   }

   void log(string message){
      if(LoggerScope.Current!=null){
          Console.WriteLine(message);
          if(LoggerScope.Current.WithTime){
             Console.WriteLine(DateTime.Now);
          }
      }
   }

}
1
Siamand Maroufi

Non che sia estremamente importante, ma l'utilizzo può anche essere usato per cambiare risorse al volo. Sì usa e getta come accennato in precedenza, ma forse nello specifico non vuoi che le risorse si mischino con altre risorse durante il resto della tua esecuzione. Quindi vuoi eliminarlo in modo che non interferisca altrove.

1
Scot McPherson

La Rhino Mocks Record-playback Syntax fa un uso interessante di using.

1
Gilligan

L'istruzione using fornisce un meccanismo di convenienza per utilizzare correttamente oggetti IDisposable. Di norma, quando si utilizza un oggetto IDisposable, è necessario dichiararlo e creare un'istanza in un'istruzione using. L'istruzione using chiama il metodo Dispose sull'oggetto nel modo corretto e (quando lo si usa come mostrato in precedenza) fa sì che l'oggetto stesso vada fuori campo non appena viene chiamato Dispose. All'interno del blocco using, l'oggetto è di sola lettura e non può essere modificato o riassegnato.

Questo proviene da: qui

1
snowell

Grazie ai commenti qui sotto, pulirò un po 'questo post (non avrei dovuto usare le parole' garbage collection 'al momento, scuse):
Quando si usa, chiamerà il metodo Dispose () sull'oggetto alla fine dell'ambito di utilizzo. Così puoi avere un bel po 'di ottimo codice di pulizia nel tuo metodo Dispose ().
Un punto elenco qui che si spera possa ottenere questo non segnalato. Se implementi IDisposable, assicurati di chiamare GC.SuppressFinalize () nell'implementazione di Dispose (), altrimenti la raccolta automatica dei rifiuti tenterà di venire avanti e ultimatelo a un certo punto, che per lo meno sarebbe uno spreco di risorse se ne avete già Dispose ().

1
Grank

Tutto ciò che è al di fuori delle parentesi graffe è disposto, quindi è fantastico disporre gli oggetti se non li si sta utilizzando. Questo perché se si dispone di un oggetto SqlDataAdapter e lo si utilizza solo una volta nel ciclo di vita dell'applicazione e si sta riempiendo solo un set di dati e non è più necessario, è possibile utilizzare il codice:

using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
   // do stuff
} // here adapter_object is disposed automatically
1
milot

La parola chiave using definisce l'ambito per l'oggetto e quindi elimina l'oggetto quando l'ambito è completo. Per esempio.

using (Font font2 = new Font("Arial", 10.0f))
{
    // use font2
}

Vedi qui per l'articolo MSDN sul C # usando la parola chiave.

1
David Basarab

Un altro esempio di un uso ragionevole in cui l'oggetto viene immediatamente eliminato:

using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString)) 
{
    while (myReader.Read()) 
    {
        MyObject theObject = new MyObject();
        theObject.PublicProperty = myReader.GetString(0);
        myCollection.Add(theObject);
    }
}
1
Brendan Kendrick

using viene utilizzato quando si dispone di una risorsa che si desidera disporre dopo che è stata utilizzata.

Ad esempio se si assegna una risorsa File e si ha solo bisogno di usarla in una sezione di codice per un po 'di lettura o scrittura, l'utilizzo è utile per lo smaltimento della risorsa File non appena eseguita.

La risorsa utilizzata deve implementare IDisposable per funzionare correttamente.

Esempio:

using (File file = new File (parameters))
{
    *code to do stuff with the file*
}
1
Bob Wintemberg