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.