Neste artigo vamos recordar o bloco de instrução using e como se comportam os métodos Close e Dispose neste contexto. |
Para permitir que o programador execute explicitamente essas atividades de limpeza, os objetos podem fornecer um método Dispose que pode ser chamado quando o objeto não for mais necessário.
A
instrução using define um limite para o objeto
fora do qual, o objeto é destruído automaticamente. A instrução
using é encerrada ao final do bloco de
instruções "using" ou quando a execução sai do
bloco indiretamente, por exemplo - quando uma exceção for lançada.
Além disso, a instrução "using" permite
especificar vários recursos em uma única instrução. O objeto também pode ser
criado fora da instrução "using".
Nota: Os objetos especificados no bloco using devem implementar a interface IDisposable.
O Framework chama o método Dispose dos objetos especificados na instrução "using" quando o bloco é encerrado.
Assim, de forma mais simples, a instrução using é usada para usar recursos e ter a certeza que estes recursos serão liberados no fim do bloco da instrução using.
A seguir temos um exemplo básico de utilização da instrução using para acesso a dados com ADO .NET:
using (SqlConnection conn = new
SqlConnection(dsn)) using (SqlCommand cmd = new SqlCommand("SELECT * FROM Clientes", conn)) { conn.Open(); using (SqlDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) Console.WriteLine(rdr[0]); } } |
Aqui usamos a instrução using para os objetos SqlConnection, SqlCommand e SqlDataReader e eles serão liberados da memória após o fim do bloco da instrução using.
Agora vejamos um exemplo de código que não usa a instrução using em um projeto do tipo Console .NET Core onde acessamos a tabela Categories do banco de dados Northwind :
No método Main() :
static void Main(string[] args)
{
SemUsarUsing();
Console.ReadKey();
}
|
Método criado sem usar a instrução using:
private static void SemUsarUsing()
{
string texto = "";
string sConnString = "Data Source=Macoratti;Initial Catalog=Northwind;Integrated Security=True";
string sSql = "SELECT CategoryID, CategoryName FROM Categories ORDER BY CategoryName";
SqlConnection cn = null;
SqlCommand cmd = null;
SqlDataReader rdr = null;
try
{
cn = new SqlConnection(sConnString);
cmd = new SqlCommand(sSql, cn);
cn.Open();
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
texto += rdr["CategoryName"].ToString() + Environment.NewLine;
}
Console.WriteLine(texto);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if ((rdr != null) && (!rdr.IsClosed))
rdr.Close();
if (cmd != null)
cmd.Dispose();
if (cn != null)
cn.Dispose();
}
}
|
Embora esse código funcione ele é muito verboso e sujeito a erros. Note que no bloco finally foi mplementado o código para liberar os recursos usados pelos objetos ADO .NET.
A seguir temos o resultado da execução do código acima:
Vamos otimizar o código com a utilização da instrução using. Veja abaixo como ficou:
private static void UsandoUsing()
{
string texto = "";
string sConnString = "Data Source=Macoratti;Initial Catalog=Northwind;Integrated Security=True";
string sSql = "SELECT CategoryID, CategoryName FROM Categories ORDER BY CategoryName";
try
{
using (SqlConnection cn = new SqlConnection(sConnString))
{
using (SqlCommand cmd = new SqlCommand(sSql, cn))
{
cn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
texto += rdr["CategoryName"].ToString() + Environment.NewLine;
}
Console.WriteLine(texto);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
|
Como vemos o código ficou mais enxuto e limpo e fácil de ler, e, não precisamos usar o bloco finally para liberar os objetos usados pois ao usar o bloco de instrução using os objetos usados serão automaticamente liberados e a conexão encerrada.
Agora atente para o fato de que qualquer coisa declarada na instrução using somente pode ser acessada apenas dentro do seu bloco. Se você quiser fazer referência a variáveis ou objetos fora da instrução using (ou bloco try), tem que declará-los antes de iniciar a instrução.
Então usamos a instrução using pois ela chama o
método 'dispose' internamente, sempre que
qualquer exceção ocorrer.
Assim todo o tipo que implementa IDisposable em
um bloco using terá os recursos liberados da
memória sem precisar esperar o coletor de lixo.
E estamos conversados...
"Bendito seja o Deus e Pai de nosso Senhor Jesus
Cristo, o Pai das misericórdias e o Deus de toda a consolação;
Que nos consola em toda a nossa tribulação, para que também possamos
consolar os que estiverem em alguma tribulação, com a consolação com que nós
mesmos somos consolados por Deus."
2 Coríntios 1:3,4
Referências:
C# - Usando Listas com elegância - Macoratti
C# - Trabalhando com Coleções Genéricas do tipo List(<T>)
C# - Diferentes maneira de criar uma lista de objetos
C# - Acessando dados de um dicionário ordenado -
C# - Usando um Dicionário para armazenar e ...
C# - Escolhendo a coleção correta para sua ...