Usuario kokos respondió a las maravillosas Características ocultas de C # question al mencionar la palabra clave using
. Puedes profundizar sobre eso? ¿Cuáles son los usos de using
?
El motivo de la declaración using
es garantizar que el objeto se elimine tan pronto como salga del alcance, y no se requiere un código explícito para garantizar que esto suceda.
Como enAl entender la instrucción 'using' en C #, el .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();
}
}
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 aún 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
}
Esta SqlConnection
se cerrará sin necesidad de llamar explícitamente a la función .Close()
, y esto sucederá incluso si se lanza una excepción , sin la necesidad de una try
/catch
/finally
.
usando 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;
utilizando, en el sentido de
using (var foo = new Bar())
{
Baz();
}
En realidad es taquigrafía para un bloque try/finally. 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 deberías hacer como limpieza incluso si se lanza una excepción. Debido a esto, hemos creado una clase que llamamos Ámbito 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 y en sentencias. Como una 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 objeto IDisposable . Como directiva, se usa de manera rutinaria 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 En pocas palabras: 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 con prudencia, ya que el abuso de esta práctica puede afectar la claridad del código de una persona. En DotNetPearls ( http://www.dotnetperls.com/using-alias ) hay una buena explicación sobre los alias de C #, que también mencionan los pros y los contras.
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 (mediante la eliminación automática de llamadas). 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();
}
}
}
Solo añadiendo un poco de algo que me sorprendió no salió. La característica más interesante de usar (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 se devuelve la lista. El objeto DbContext siempre será eliminado.
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 variables no locales IDisposable
, entonces always implemente el patrón IDisposable
.
Dos reglas simples, sin excepción.1. Prevenir las fugas de recursos de lo contrario es un verdadero dolor en la * ss.
1): La única excepción es cuando se manejan excepciones. Entonces podría haber menos código para llamar a Dispose
explícitamente en el bloque finally
.
Puede hacer uso del espacio de nombres de alias mediante el siguiente ejemplo:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Esto se denomina usando la directiva de alias como puede ver, se puede usar para ocultar referencias largas si desea que sea evidente en su código a qué 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
Curiosamente, también puede utilizar el patrón de uso/IDisposable para otras cosas interesantes (como el otro punto de la forma en que Rhino Mocks lo utiliza). Básicamente, puede aprovechar el hecho de que el compilador siempre llamará .Disponer al 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 IDisposible que inicie la operación en el constructor, y luego finalice en el método de Disposición.
Esto le permite usar la sintaxis realmente agradable para indicar el inicio y el final explícitos de dicha operación. Así es también como funcionan las cosas de System.Transactions.
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
}
}
Cuando use ADO.NET, puede usar el trabajo de teclas para cosas como su objeto de conexión o su objeto lector. De esa manera, cuando el bloque de código se complete, se eliminará automáticamente de su conexión.
"using" también se puede utilizar para resolver conflictos de espacio de nombres. Consulte http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ para un breve tutorial que escribí sobre el tema.
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, debe usar el bloque 'using' para las clases que requieren limpieza después de ellas, como los tipos System.IO.
Hay dos usos del uso de palabras clave en C # de la siguiente manera.
En general, usamos la palabra clave using para agregar espacios de nombres en los archivos de código subyacente y de clase. 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;
Esta es otra forma de usar la palabra clave using en C #. Juega 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 métodos de llamada, 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 base de datos (Insertar, Actualizar, Eliminar) pero de alguna manera ocurre una excepción, aquí la instrucció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. 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 de 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 buscará los objetos disponibles en el grupo. Así que ayuda a mejorar el rendimiento de la aplicación. Por lo tanto, cuando usamos la instrucción de uso, el controlador envía el objeto a la agrupación de conexiones automáticamente, no hay necesidad de llamar a los métodos Cerrar () y Dispose () explícitamente.
Puede hacer lo mismo que hace la instrucción utilizando el bloque try-catch y llamar a Dispose () dentro del bloque finally de manera explícita. Pero la declaración de uso realiza las llamadas automáticamente para hacer que el código sea más limpio y elegante. Dentro del bloque que usa, 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 estoy cerrando ninguna conexión, se cerrará automáticamente. La instrucción using llamará a conn.Close () automáticamente debido a la instrucción using (utilizando (SqlConnection conn = new SqlConnection (connString)) y lo mismo para un objeto SqlDataReader. Y también, si se produce alguna excepción, cerrará la conexión automáticamente.
Para obtener más información -> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/
Para mí, el nombre "usar" es un poco confuso, ya que 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 Niza, y tal vez uno más obvio.
También se puede utilizar para crear ámbitos para 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);
}
}
}
}
No es que sea muy importante, pero el uso también se puede usar para cambiar recursos sobre la marcha. Sí, disponible como se mencionó anteriormente, pero tal vez específicamente no desea que los recursos no coincidan con otros recursos durante el resto de su ejecución. Así que quieres deshacerte de él para que no interfiera en ningún otro lado.
Sintaxis de Rhino Mocks Record-playback hace un uso interesante de using
.
La declaración de uso proporciona un mecanismo de conveniencia para usar correctamente objetos IDisposibles. Como regla general, cuando utiliza un objeto IDisposable, debe declararlo y crear una instancia en una instrucción using. La declaración de uso llama al método Dispose sobre el objeto de la manera correcta, y (cuando lo usa como se muestra anteriormente) también hace que el objeto salga del ámbito tan pronto como se llame a Dispose. Dentro del bloque que usa, el objeto es de solo lectura y no se puede modificar ni reasignar.
Esto viene de: aquí
Gracias a los comentarios a continuación, limpiaré esta publicación un poco (no debería haber usado las palabras 'recolección de basura' en ese momento, disculpas):
Cuando use, llamará al método Dispose () en el objeto al final del alcance del uso. Por lo tanto, puede tener un buen código de limpieza en su método Dispose ().
Un punto importante aquí que posiblemente obtenga este desmarque: Si implementas IDisposable, asegúrate de llamar a GC.SuppressFinalize () en tu implementación de Dispose (), ya que de lo contrario la recolección automática de basura intentará aparecer y finalícelo en algún momento, lo que al menos sería un desperdicio de recursos si ya dispone de Disposición () d.
Todo lo que se encuentra fuera de las llaves está dispuesto, por lo que es bueno desechar sus 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 palabra clave using define el alcance del objeto y luego lo desecha cuando el alcance está completo. Por ejemplo.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Vea aquí para el artículo de MSDN sobre el C # usando la palabra clave.
Otro ejemplo de un 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);
}
}
usar se usa 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 del código para leer o escribir un poco, usarlo es útil para deshacerse del recurso de archivo tan pronto como lo haya hecho.
El recurso que se está utilizando debe implementarse como IDisposable para funcionar correctamente.
Ejemplo:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}