Pregunta

Usuario kokos respondió el maravilloso Funciones ocultas de C# pregunta mencionando el using palabra clave.Puedes profundizar sobre eso?¿Cuáles son los usos de using?

¿Fue útil?

Solución

El motivo de la using La declaración es para garantizar que el objeto se elimine tan pronto como salga del alcance, y no requiere código explícito para garantizar que esto suceda.

Como en Comprender la declaración 'usar' en C#, .NET CLR convierte

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();
    }
}

Otros consejos

Como mucha gente todavía lo hace:

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

Supongo que mucha gente todavía no sabe que se puede hacer:

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

Cosas como esta:

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

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

Este SqlConnection se cerrará sin necesidad de llamar explícitamente al .Close() funcionar, y esto sucederá incluso si se lanza una excepción, sin necesidad de un try/catch/finally.

El uso se puede utilizar para llamar a IDisposable.También se puede utilizar para tipos de alias.

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

usando, en el sentido de

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

En realidad, es una abreviatura de bloque try/finally.Es equivalente al código:

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

Por supuesto, notarás que el primer fragmento es mucho más conciso que el segundo y también que hay muchos tipos de cosas que quizás quieras hacer como limpieza incluso si se produce una excepción.Debido a esto, creamos una clase que llamamos Scope que le permite ejecutar código arbitrario en el método Dispose.Entonces, por ejemplo, si tuviera una propiedad llamada IsWorking que siempre quisiera establecer en falso después de intentar realizar una operación, lo haría así:

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

Puede leer más sobre nuestra solución y cómo la obtuvimos. aquí.

Lo he usado mucho en el pasado para trabajar con flujos de entrada y salida.Puede anidarlos muy bien y elimina muchos de los problemas potenciales con los que normalmente se encuentra (llamando automáticamente a disponer).Por ejemplo:

        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();
                }
            }
        }

La documentación de Microsoft establece que usando tiene una doble función (https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx), tanto como directiva y en declaraciones.Como un declaración, como se señaló aquí en otras respuestas, la palabra clave es básicamente azúcar sintáctica para determinar un alcance para disponer de un Desechable objeto.Como un directiva, se utiliza habitualmente para importar espacios de nombres y tipos.También como directiva, puedes crear alias para espacios de nombres y tipos, como se señala en el libro "C# 5.0 In a Nutshell:La guía definitiva" (http://www.amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8), de Joseph y Ben Albahari.Un ejemplo:

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;
        }
    }
}

Esto es algo que se debe adoptar sabiamente, ya que el abuso de esta práctica puede dañar la claridad del código.Hay una buena explicación sobre los alias de C#, que también menciona los pros y los contras, en DotNetPearls (http://www.dotnetperls.com/using-alias).

Solo agregué algo que me sorprendió y no apareció.La característica más interesante de usar (en mi opinión) es que no importa cómo salgas del bloque de uso, siempre eliminará el objeto.Esto incluye devoluciones y excepciones.

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

No importa si se lanza la excepción o se devuelve la lista.El objeto DbContext siempre será eliminado.

Otro gran uso del uso es al crear una instancia de un diálogo modal.

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using

En conclusión, cuando utiliza una variable local de un tipo que implementa IDisposable, siempre, sin excepción, utilizar using1.

Si usas no local IDisposable variables, entonces siempre implementar el IDisposable patrón.

Dos reglas simples, sin excepción1.De lo contrario, evitar fugas de recursos es un verdadero dolor de cabeza.


1):La única excepción es cuando manejas excepciones.Entonces podría haber menos código para llamar Dispose explícitamente en el finally bloquear.

Curiosamente, también puedes usar el patrón using/IDisposable para otras cosas interesantes (como el otro punto de la forma en que Rhino Mocks lo usa).Básicamente, puedes aprovechar el hecho de que el compilador siempre llame a .Dispose en el objeto "usado".Si tiene algo que debe suceder después de una determinada operación...algo que tiene un comienzo y un final definidos...luego, simplemente puede crear una clase IDisposable que inicie la operación en el constructor y luego finalice en el método Dispose.

Esto le permite utilizar la sintaxis de uso realmente agradable para indicar el inicio y el final explícitos de dicha operación.Así es también como funciona el sistema System.Transactions.

Puede utilizar el espacio de nombres de alias mediante el siguiente ejemplo:

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

Esto se llama un usando la directiva alias Como puede ver, se puede usar para ocultar referencias de largo aliento si desea que sea obvio en su código a lo que se refiere, por ejemplo

LegacyEntities.Account

en lugar de

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

o simplemente

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

Cuando usa ADO.NET, puede usar el trabajo de claves para cosas como su objeto de conexión u objeto lector.De esa manera, cuando se complete el bloque de código, eliminará automáticamente su conexión.

"using" también se puede utilizar para resolver conflictos de espacio de nombres.Ver http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ para un breve tutorial que escribí sobre el tema.

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 
            }
    }

usando se utiliza cuando tiene un recurso que desea eliminar después de haber sido utilizado.

Por ejemplo, si asigna un recurso de Archivo y solo necesita usarlo en una sección de código para leer o escribir un poco, usarlo es útil para deshacerse del recurso de Archivo tan pronto como haya terminado.

El recurso que se utiliza debe implementar IDisposable para funcionar correctamente.

Ejemplo:

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

La palabra clave use define el alcance del objeto y luego elimina el objeto cuando el alcance está completo.Por ejemplo.

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

Ver aquí para el artículo de MSDN sobre C# usando la palabra clave.

No es que sea muy importante, pero el uso también se puede utilizar para cambiar recursos sobre la marcha.Sí, desechable como se mencionó anteriormente, pero quizás específicamente no desee que los recursos no coincidan con otros recursos durante el resto de su ejecución.Por lo tanto, desea deshacerse de él para que no interfiera en otros lugares.

Gracias a los comentarios a continuación, limpiaré un poco esta publicación (no debería haber usado las palabras "recolección de basura" en ese momento, disculpas):
Cuando usas, llamará al método Dispose() en el objeto al final del alcance del uso.Por lo tanto, puede tener bastante código de limpieza excelente en su método Dispose().
Una viñeta aquí que, con suerte, tal vez elimine esta reducción:Si implementa IDisposable, asegúrese de llamar a GC.SuppressFinalize() en su implementación de Dispose(), ya que de lo contrario la recolección automática de basura intentará aparecer y finalizarlo en algún momento, lo que al menos sería un desperdicio de recursos si Ya lo he eliminado.

Otro ejemplo de uso razonable en el que el objeto se dispone inmediatamente:

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);
    }
}

Todo lo que está fuera de las llaves se desecha, por lo que es fantástico deshacerse de los objetos si no los está utilizando.Esto es así porque si tienes un objeto SqlDataAdapter y lo estás usando solo una vez en el ciclo de vida de la aplicación y estás completando solo un conjunto de datos y ya no lo necesitas, puedes usar el código:

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

La declaración de uso proporciona un mecanismo conveniente para usar correctamente los objetos IDisposable.Como regla general, cuando usa un objeto IDisposable, debe declararlo y crear una instancia del mismo en una declaración de uso.La declaración de uso llama al método Dispose en el objeto de la manera correcta y (cuando lo usa como se mostró anteriormente) también hace que el objeto en sí quede fuera de alcance tan pronto como se llama a Dispose.Dentro del bloque de uso, el objeto es de solo lectura y no se puede modificar ni reasignar.

Esto viene de: aquí

Para mí, el nombre "usar" es un poco confuso, porque puede ser una directiva para importar un espacio de nombres o una declaración (como la que se analiza aquí) para el manejo de errores.

Hubiera estado bien un nombre diferente para el manejo de errores, y tal vez uno más obvio.

También se puede utilizar para crear ámbitos, por ejemplo:

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);
          }
      }
   }

}

La declaración de uso le dice a .NET que libere el objeto especificado en el bloque de uso una vez que ya no sea necesario.Por lo tanto, debería usar el bloque 'usar' para las clases que requieren limpieza después de ellas, como System.IO Types.

Hay dos usos del uso de palabras clave en C# de la siguiente manera.

  1. como directiva

Generalmente usamos la palabra clave using para agregar espacios de nombres en archivos de clase y de código subyacente.Luego pone a disposición todas las clases, interfaces y clases abstractas y sus métodos y propiedades en la página actual.

Ex:

using System.IO;  
  1. como una declaración

Esta es otra forma de utilizar la palabra clave using en C#.Desempeña un papel vital en la mejora del rendimiento en la recolección de basura.La declaración de uso garantiza que se llame a Dispose() incluso si se produce una excepción al crear objetos y llamar a métodos, propiedades, etc.Dispose() es un método que está presente en la interfaz IDisposable y que ayuda a implementar la recolección de basura personalizada.En otras palabras, si estoy realizando alguna operación en la base de datos (Insertar, Actualizar, Eliminar) pero de alguna manera ocurre una excepción, entonces aquí la declaración de uso cierra la conexión automáticamente.No es necesario llamar explícitamente al método Close() de conexión.

Otro factor importante es que ayuda en la agrupación de conexiones.Connection Pooling en .NET ayuda a eliminar el cierre de una conexión de base de datos varias veces.Envía el objeto de conexión a un grupo para uso futuro (próxima llamada a la base de datos).La próxima vez que se llame a una conexión de base de datos desde su aplicación, el grupo de conexiones recupera los objetos disponibles en el grupo.Por lo que ayuda a mejorar el rendimiento de la aplicación.Entonces, cuando usamos la declaración de uso, el controlador envía el objeto al grupo de conexiones automáticamente, no hay necesidad de llamar explícitamente a los métodos Close() y Dispose().

Puede hacer lo mismo que hace la declaración de uso usando el bloque try-catch y llamando explícitamente a Dispose() dentro del bloque finalmente.Pero la declaración de uso realiza las llamadas automáticamente para que el código sea más limpio y elegante.Dentro del bloque de uso, el objeto es de solo lectura y no se puede modificar ni reasignar.

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));  
      }  
}  

En el código anterior no cierro ninguna conexión, se cerrará automáticamente.La declaración de uso llamará a conn.Close() automáticamente debido a la declaración de uso (using (SqlConnection conn = new SqlConnection(connString)) y lo mismo para un objeto SqlDataReader.Y además si ocurre alguna excepción cerrará la conexión automáticamente.

Para más información --> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

El uso de una declaración llama automáticamente la eliminación en el objeto especificado.El objeto debe implementar la interfaz IDisposable.Es posible usar varios objetos en una declaración siempre que sean del mismo tipo.

El CLR convierte su código en MSIL.Y la declaración de uso se traduce en un bloque de prueba y finalmente.Así es como se representa la declaración de uso en IL.Una declaración de uso se traduce en tres partes:adquisición, uso y enajenación.Primero se adquiere el recurso, luego el uso se incluye en una declaración de prueba con una cláusula finalmente.Luego, el objeto se elimina en la cláusula final.

La cláusula de uso se utiliza para definir el alcance de la variable en particular.Por ejemplo:

     Using(SqlConnection conn=new SqlConnection(ConnectionString)
            {
                Conn.Open()
            // Execute sql statements here.
           // You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
            }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top