Quando programamos em C#, é bastante comum a
prática e utilização do bloco using.
Muitas pessoas o utilizam, e gostaria de falar um pouco sobre qual o objetivo
deste bloco e como ele funciona dentro do .NET Framework.
O bloco
using provê ao desenvolvedor a
habilidade de se criar um bloco de código isolado dentro de um determinado
programa. Podemos com ele, atingir dois objetivos:
·
Criar um alias para um determinado namespace
ou tipo;
·
Criar um escopo que ao final de sua execução,
libera recursos automaticamente através do método Dispose().
Exemplo:
using (System.Data.SqlClient.SqlConnection
conn = new System.Data.SqlClient.SqlConnection())
{
}
No bloco acima, estamos fazendo referência ao
namespace System.Data.SqlClient e
criando o alias através da variável conn. Com isso podemos trabalhar com todas
as funcionalidades da classe instanciada, sem termos que nos preocupar se os
recursos serão liberados após sua utilização ou se a conexão será realmente
encerrada.
Como isso acontece?
É importante lembrar que para a utilização do
bloco using, necessita-se que a
classe usada no escopo, implemente a interface IDisposable, ou seja, a classe deve implementar o método Dispose que está dentro das exigências
da interface IDisposable, e neste
método deve ser especificado como os recursos utilizados serão liberados na
memória. Com isso, automaticamente no final do bloco using, o método Dispose é
invocado pela CLR (Common Language
Runtime).
Se formos nas definições da classe SqlConnection, iremos ver que a mesma
herda de DbConnection que por sua vez
implementa a interface IDisposable;
por isso conseguimos utilizá-la no bloco using.
Abaixo, iremos criar uma classe simples que utiliza
estes conceitos.
Apenas como exemplo didático, será criada uma
classe que efetua a leitura de um arquivo físico localizado no computador
(através da classe StreamReader –
localizada no namespace System.IO).
class FileReader
{
StreamReader sReader;
public FileReader(string path)
{
sReader = new StreamReader(path);
}
public string GetText()
{
return sReader.ReadToEnd();
}
}
Ao instanciarmos esta classe, devemos
especificar qual o caminho do arquivo, e o método GetText lê todas as linhas do
arquivo e as retornam dentro de uma string.
Vamos agora utilizá-la dentro de um bloco using:
using (FileReader fReader
= new FileReader(@"C:\temp\Arquivo.txt"))
{
Console.WriteLine("Conteúdo
do arquivo: {0}.", fReader.GetText());
}
Repare que no momento de compilar o código, ocorrerá um erro nos alertando que o tipo usado dentro do bloco using (classe FilReader) não implementa a interface IDisposable.
Sendo assim, vamos agora fazer os devidos ajustes na
classe FileReader de forma que ela
possa implementar a interface IDisposable
e ser utilizada corretamente dentro do bloco using.
Para isso, basta acrescentarmos o seguinte código na
definição da classe:
class FileReader: IDisposable
{
...
}
Ao especificarmos que nossa classe implementa a interface
IDisposable, teremos que criar obrigatoriamente
um método Dispose dentro da mesma.
Para isso basta clicarmos com o botão direito em cima de IDisposable e clicar em “Implement
Interface”, com isso será criado
automaticamente o método Dispose:
public void Dispose()
{
throw new NotImplementedException();
}
Por padrão, dentro do método Dispose, será criado uma exceção de método não implementado, porém,
devemos criar a nossa codificação apropriada para o método Dispose. Como em nossa classe utilizamos apenas o recurso StreamReader, vamos então efetuar o
fechamento do arquivo para que o mesmo não fique aberto e consuma recursos:
public void Dispose()
{
sReader.Close();
}
Com isso, estaremos dizendo para o compilador “Ei, minha
classe agora implementa a interface IDisposable!”,
e assim poderemos utilizá-la perfeitamente no bloco using.
Compile o código novamente.
Para visualizar o funcionamento da liberação de recursos da classe FileReader, coloque um ponto de parada dentro do bloco using, e perceba que logo após a execução do bloco, o método Dispose de FileReader é invocado, efetuando assim todos os procedimentos necessários para a liberação de recursos.
Veja como ficou a classe:
class FileReader: IDisposable
{
StreamReader sReader;
public FileReader(string path)
{
sReader = new StreamReader(path);
}
public
string GetText()
{
return sReader.ReadToEnd();
}
public void Dispose()
{
sReader.Close();
Espero que tenham gostado, até a próxima.