El usuario kokos respondió la maravillosa pregunta de Características ocultas de C # mencionando la using
palabra clave. Puedes profundizar sobre eso? ¿Para qué sirven using
?
El usuario kokos respondió la maravillosa pregunta de Características ocultas de C # mencionando la using
palabra clave. Puedes profundizar sobre eso? ¿Para qué sirven using
?
Respuestas:
El motivo de la using
declaración es garantizar que el objeto se elimine tan pronto como salga del alcance, y no requiere un código explícito para garantizar que esto suceda.
Al igual que en Comprender la instrucción 'using' en C # (proyecto de código) y Usar objetos que implementan IDisposable (microsoft) , el compilador de C # 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();
}
}
C # 8 presenta una nueva sintaxis, llamada " usando declaraciones ":
Una declaración de uso es una declaración variable precedida por la palabra clave de uso. Le dice al compilador que la variable que se declara debe eliminarse al final del ámbito de inclusión.
Entonces el código equivalente de arriba sería:
using var myRes = new MyResource();
myRes.DoSomething();
Y cuando el control abandone el ámbito de contención (generalmente un método, pero también puede ser un bloque de código), myRes
se eliminará.
using
se asegura de que Dispose
se llame una vez que haya terminado con el objeto.
MyRessource
es una estructura. Obviamente no hay prueba de nulidad, pero tampoco hay boxeo IDisposable
. Se emite una llamada virtual restringida.
using
, la variable construida dentro es de solo lectura. No hay forma de lograr esto para las variables locales sin la using
declaración.
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 puedes 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
}
Esto SqlConnection
se cerrará sin necesidad de llamar explícitamente a la .Close()
función, y esto sucederá incluso si se produce una excepción , sin la necesidad de un try
/ catch
/ finally
.
return
en el medio del using
bloque.
utilizando, en el sentido de
using (var foo = new Bar())
{
Baz();
}
En realidad es una forma abreviada de un intento / finalmente bloquear. Es equivalente al código:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Notarás, por supuesto, 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 lanza una excepción. Debido a esto, hemos creado 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 quiso 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 derivamos aquí .
La documentación de Microsoft indica que usar tiene una doble función ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ), tanto como directiva como en declaraciones . Como una declaración , como se señaló aquí en otras respuestas, la palabra clave es básicamente azúcar sintáctica para determinar el alcance para disponer de un objeto desechable ID . Como directiva , se usa habitualmente para importar espacios de nombres y tipos. También como directiva, puede crear alias para espacios de nombres y tipos, como se señala en el libro "C # 5.0 In a Nutshell: The Definitive Guide" ( http://www.amazon.com/5-0-Nutshell-The- Libro de referencia definitivo / 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 para 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 ).
using
como una herramienta de alias. Me confunde al leer el código: ya sé que System.Collections
existe y que tiene la IEnumerable<T>
clase. Usar un alias para llamarlo de otra manera lo ofusca. Veo using FooCollection = IEnumerable<Foo>
como una forma de hacer que los desarrolladores posteriores lean el código y piensen: "¿Qué demonios es FooCollection
y por qué no hay una clase para eso en alguna parte?" Nunca lo uso y desalentaría su uso. Pero eso podría ser solo yo.
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 generalmente se encuentra (llamando automáticamente a dispose). 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();
}
}
}
Simplemente agregué un pequeño detalle que me sorprendió no surgió. La característica más interesante del uso (en mi opinión) es que no importa cómo salga 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 si se devuelve la lista. El objeto DbContext siempre se eliminará.
Otro gran uso del uso es cuando se crea una instancia de un diálogo modal.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
En conclusión, cuando usa una variable local de un tipo que implementa IDisposable
, siempre , sin excepción, use using
1 .
Si usa IDisposable
variables no locales , siempre implemente el IDisposable
patrón .
Dos reglas simples, sin excepción 1 . La prevención de fugas de recursos de lo contrario es un verdadero dolor en el * ss.
1) : La única excepción es: cuando maneja excepciones. Entonces podría ser menos código para llamar Dispose
explícitamente en el finally
bloque.
Puede utilizar el espacio de nombres de alias mediante el siguiente ejemplo:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Esto se llama una directiva de uso de alias , como puede ver, se puede usar para ocultar referencias largas en caso de que desee hacer obvio en su código a qué se refiere, por ejemplo
LegacyEntities.Account
en vez de
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
o simplemente
Account // It is not obvious this is a legacy entity
Curiosamente, también puede usar el patrón de uso / IDisposable para otras cosas interesantes (como el otro punto de la forma en que Rhino Mocks lo usa). Básicamente, puede aprovechar el hecho de que el compilador siempre llamará a .Dispose en el objeto "usado". Si tiene algo que debe suceder después de una determinada operación ... algo que tiene un inicio y un final definidos ... entonces simplemente puede hacer una clase IDisposable que comience la operación en el constructor y luego termine en el método Dispose.
Esto le permite utilizar la sintaxis de uso realmente agradable para denotar el inicio y el final explícitos de dicha operación. Así es también como funciona el material System.Transactions.
Cuando use ADO.NET, puede usar el trabajo de teclado para cosas como su objeto de conexión u objeto lector. De esa manera, cuando el bloque de código se complete, eliminará automáticamente su conexión.
"usar" también se puede usar 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
}
}
El uso se utiliza cuando tiene un recurso que desea eliminar después de que se haya 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 termine.
El recurso que se utiliza debe implementar IDisposable para que funcione correctamente.
Ejemplo:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
La palabra clave using define el alcance del objeto y luego desecha el objeto cuando se completa el alcance. Por ejemplo.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Consulte aquí el artículo de MSDN sobre C # usando la palabra clave.
No es que sea extremadamente importante, pero el uso también se puede usar para cambiar recursos sobre la marcha. Sí, desechable como se mencionó anteriormente, pero quizás específicamente no desea que los recursos no coincidan con otros recursos durante el resto de su ejecución. Por lo tanto, debe deshacerse de él para que no interfiera en otro lugar.
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 use el uso, llamará al método Dispose () en el objeto al final del alcance del uso. Por lo tanto, puede tener un código de limpieza bastante bueno en su método Dispose ().
Una viñeta aquí que con suerte tal vez no se marque: si implementa IDisposable, asegúrese de llamar a GC.SuppressFinalize () en su implementación Dispose (), ya que de lo contrario la recolección automática de basura intentará aparecer y finalizarla en algún momento punto, que al menos sería un desperdicio de recursos si ya ha dispuesto () d de él.
Otro ejemplo de uso razonable en el que el objeto se elimina 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 los corchetes se desecha, por lo que es excelente deshacerse de los objetos si no los está utilizando. Esto es así porque si tiene un objeto SqlDataAdapter y lo está usando solo una vez en el ciclo de vida de la aplicación y está llenando solo un conjunto de datos y ya no lo necesita, puede usar el código:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
La instrucción de uso proporciona un mecanismo de conveniencia para usar correctamente los objetos IDisposable. Como regla general, cuando usa un objeto IDisposable, debe declararlo e instanciarlo en una declaración de uso. La instrucción using llama al método Dispose en el objeto de la manera correcta y (cuando lo usa como se muestra anteriormente) también hace que el objeto se salga del alcance tan pronto como se llame 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.
Un nombre diferente para el manejo de errores hubiera sido bueno, y tal vez uno de alguna manera más obvio.
También se puede usar 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 instrucció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, debe usar el bloque 'usar' para las clases que requieren limpieza después de ellas, como los Tipos System.IO.
Hay dos usos de la using
palabra clave en C # de la siguiente manera.
Como directiva
Generalmente usamos la using
palabra clave 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.
Ejemplo:
using System.IO;
Como una declaración
Esta es otra forma de usar la using
palabra clave en C #. Desempeña un papel vital en la mejora del rendimiento en la recolección de basura.
La using
instrucción 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 que ayuda a implementar la recolección de basura personalizada. En otras palabras, si estoy haciendo alguna operación de la base de datos (Insertar, Actualizar, Eliminar) pero de alguna manera ocurre una excepción, aquí la declaración de uso cierra la conexión automáticamente. No es necesario llamar al método de conexión Close () explícitamente.
Otro factor importante es que ayuda en la agrupación de conexiones. La agrupación de conexiones 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 busca los objetos disponibles en el grupo. Por lo tanto, 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 lo que está haciendo la instrucción using utilizando el bloque try-catch y llamando a Dispose () dentro del bloque finalmente explícitamente. Pero la declaración de uso hace 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.
Ejemplo:
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 estoy cerrando ninguna conexión; Se cerrará automáticamente. La using
instrucción llamará a conn.Close () automáticamente debido a la using
instrucción ( using (SqlConnection conn = new SqlConnection(connString)
) y lo mismo para un objeto SqlDataReader. Y también, si ocurre alguna excepción, cerrará la conexión automáticamente.
Para obtener más información, consulte Uso e importancia del uso en C # .
La sintaxis de reproducción de registros de Rhino Mocks hace un uso interesante de using
.
usar como una declaración llama automáticamente a la disposició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 intento y finalmente se bloquea. Así es como se representa la instrucción using en IL. Una declaración de uso se traduce en tres partes: adquisición, uso y eliminación. El recurso se adquiere primero, luego el uso se incluye en una declaración de prueba con una cláusula finalmente. El objeto se elimina en la cláusula final.
El uso de Cláusula se utiliza para definir el alcance de la variable 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.
}