Parte I de este artículo.
Implementación
El uso del estamento Using requiere de la implementación de la interfaz IDispose. Ello es debido a que cuando trabajamos con objetos, estos requieren una liberación de sus recursos en la memoria de forma segura en el sistema. Para ello se acude al uso del método Dispose().
La ventaja de utilizar el estamento Using es la facilidad de su construcción y uso del código. Esta simplificación del código tendrá como misión la de escribir y limpiar finalmente los recursos de dicho objeto afectado. En consecuencia, el estamento Using obtiene el recurso específico, luego pasa a ejecutarlo y finalmente pasa a llamar al método Dispose() del objeto en cuestión, a los efectos de limpiarlo y liberarlo de la memoria del sistema. Obviamente, todo esto es instrumentado con la ayuda del GC (Garbage Colector) “Recolector de Basura“.
Veamos un ejemplo sencillo aplicado para la gestión de un archivo de texto plano clásico. Recuerda que la gestión de archivos, requiere de tres pasos importantes. Estos deben ser llevados a cabo de forma eficiente. Los pasos son “Abrir el archivo“, “gestionar sus recursos internos” y por último, “Cerrar el archivo“.
Ejemplo con Archivo Plano – Visual VB.NET
Using w As TextWriter = File.CreateText(“anotaciones.txt”)
w.WriteLine(“Esta es una línea.”)
End Using
Ejemplo con Archivo Plano – Visual C#
w.WriteLine(“Esta es una línea.”)
End Using
Ejemplo con Archivo Plano – Visual C#
using (TextWriter w = File.CreateText(“anotaciones.txt”))
{
w.WriteLine(“Esta es una línea.”);
}
{
w.WriteLine(“Esta es una línea.”);
}
Tenemos que recordar que el uso del estamento Using obliga a que el código se ejecute en modo No Administrado. Por tanto, el IL (Intermediate Language) tendrá un proceso operativo bastante especial. El IL podría quedar reducido al siguiente contexto ensamblado.
Resultado del Ejemplo con IL
.locals init ([0] class [mscorlib]System.IO.TextWriter w)
IL_0000: ldstr “anotaciones.txt”
IL_0005: call class [mscorlib]System.IO.StreamWriter
[mscorlib]System.IO.File::CreateText(string)
IL_000a: stloc.0
IL_0000: ldstr “anotaciones.txt”
IL_0005: call class [mscorlib]System.IO.StreamWriter
[mscorlib]System.IO.File::CreateText(string)
IL_000a: stloc.0
.try
{
IL_000b: ldloc.0
IL_000c: ldstr “This is line one”
IL_0011: callvirt instance void [mscorlib]
System.IO.TextWriter::WriteLine(string)
IL_0016: leave.s IL_0022
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: brfalse.s IL_0021
IL_001b: ldloc.0
IL_001c: callvirt instance void [mscorlib]
System.IDisposable::Dispose()
IL_0021: endfinally
} // end handler
{
IL_000b: ldloc.0
IL_000c: ldstr “This is line one”
IL_0011: callvirt instance void [mscorlib]
System.IO.TextWriter::WriteLine(string)
IL_0016: leave.s IL_0022
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: brfalse.s IL_0021
IL_001b: ldloc.0
IL_001c: callvirt instance void [mscorlib]
System.IDisposable::Dispose()
IL_0021: endfinally
} // end handler
¿Qué ha pasado entonces?, ¿cómo que en el asemblado incorpore una estructura Try…Catch?, eso mismo no lo he escrito. Calma, esto tiene una explicación. Veamos.
El CLR (Common Language Runtime) convierte el código dentro del MSIL (Microsoft Intermediate Language). El estamento Using transcribe todo ello a un bloque Try…Catch, como podemos apreciar. Por tanto, se transcribe dentro de tres partes y estas son “adquisición“, “uso” y “descarga“. Ello quiere decir que el objeto es primeramente “adquirido“, luego es utilizado “usado” dentro de un contexto de bloque Try…Catch que incluye la cláusula reservada Finally y, finalmente, se procede a realizar su “descarga” a través de la cláusula Finally del propio bloque Try…Catch.
Ahora bien, este estamento Using podría corresponder a dos tipos de expansiones. Cuando se trata de un recurso de tipo valor, la expansión del bloque en la cláusula Finally podría ser la siguiente.
VB.NET – (Extracto de código)
Finally
res = DirectCast(res, IDisposable)
res.Dispose()
res = DirectCast(res, IDisposable)
res.Dispose()
Visual C# – (Extracto de código)
finally {
((IDisposable)myRes).Dispose();
}
((IDisposable)myRes).Dispose();
}
Ahora bien, cuando se trata de un recurso de tipo de referencia, la expasión del bloque en la cláusula Finally podría ser la siguiente.
VB.NET – (Extracto de código)
Finally
If Not res Is Nothing Then
res = DirectCast(res, IDisposable)
res.Dispose()
End If
If Not res Is Nothing Then
res = DirectCast(res, IDisposable)
res.Dispose()
End If
Visual C# – (Extracto de código)
finally {
if (myRes!= null)
(( IDisposable ) ).Dispose();
}
if (myRes!= null)
(( IDisposable ) ).Dispose();
}
Por tanto, cuando el recurso adquirido es null o Nothing “nulo”, a continuación se procede a llamar al método Dispose(), de modo de evitar una excepción.
Con entendimiento. Este proceso permite agilizar el manejo de los recursos de los objetos tanto cuando son tratados como valores o como referencias. La gestión No Administrada, permite agilizar la velocidad substancialmente de los procesos de ejecución de las aplicaciones.
Ahora veamos un caso más para el uso de código No Administrado para consumir recursos desde base de datos.
Ejemplo con Bases de Datos – Visual VB.NET
Dim strConn As String = “Data Source=localhost;Integrated ” _
& “Security=SSPI;Initial Catalog=Northwind;”
& “Security=SSPI;Initial Catalog=Northwind;”
Using conn As SqlConnection = New SqlConnection (strConn)
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = “SELECT ID, Name FROM Customers”
cmd.Open()
Using dr As SqlDataReader = cmd.ExecuteScaler()
While (dr.Read())
Console.WriteLine(“{0}\t{1}”, dr.GetString(0), dr.GetString(1))
End While
End Using
End Using
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = “SELECT ID, Name FROM Customers”
cmd.Open()
Using dr As SqlDataReader = cmd.ExecuteScaler()
While (dr.Read())
Console.WriteLine(“{0}\t{1}”, dr.GetString(0), dr.GetString(1))
End While
End Using
End Using
Ejemplo con Bases de Datos – Visual C#
string strConn = “Data Source=localhost;Integrated ” +
“Security=SSPI;Initial Catalog=Northwind;”;
“Security=SSPI;Initial Catalog=Northwind;”;
using (SqlConnection conn = new SqlConnection (strConn))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = “SELECT ID, Name FROM Customers”;
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine(“{0}\t{1}”, dr.GetString(0), dr.GetString(1));
}
}
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = “SELECT ID, Name FROM Customers”;
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine(“{0}\t{1}”, dr.GetString(0), dr.GetString(1));
}
}
Resumen General
El estamento Using se trata solamente de una herramienta para objetos cuyo cíclo de vida no se extienda más allá de los métodos en que el objeto ha sido construido. Recordemos que los objetos son instancias de la implementación desde la interfaz System.IDisposable.
Parte I de este artículo.
Muchas gracias. Hasta otra entrega.
No hay comentarios:
Publicar un comentario