Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

"using" quebrando ideia do "catch" no exemplo da aula?

Fiquei com dúvida sobre a substituição do bloco try/catch/finally pelo bloco using, pois no código anterior nós tinhamos o catch() para pegar os erros que acontecessem durante a execução da leitura do arquivo ou leitura de linha, etc.

Por mais que fique um código mais limpo e além, como explicado, using se refere somente ao try/finally, ou seja, a aplicação será interrompida se houver qualquer exceção. Correto?

Nesse caso se torna realmente viável usar using ao invés do try/catch/finally?

Segue os dois códigos:

Se qualquer exceção ocorrer, poderá ser tratada no catch para haver um retorno amigável. (considerando mais exceções e não só a IOException)

LeitorDeArquivo leitor = null;
try
{
    leitor = new LeitorDeArquivo("contas.txt");
    leitor.LerProximaLinha();
    leitor.LerProximaLinha();
    leitor.LerProximaLinha();
}
catch (IOException ex)
{
    Console.WriteLine("Exception do tipo IOException foi tratada.");
}
finally
{
    if (leitor != null)
        leitor.Dispose();
}

Se ocorrer uma exceção no construtor do LeitorDeArquivo ou em LerProximaLinha(), a aplicação será interrompida.

using (var leitor = new LeitorDeArquivo("contas.txt"))
{
    leitor.LerProximaLinha();
    leitor.LerProximaLinha();
    leitor.LerProximaLinha();
}
7 respostas

Olá Jean,

Na minha opinião, sempre utilize o using e o try/cath juntos.

O using irá liberar os recursos o mais breve possível , exemplo: Para que outro programa tbm consiga ler o mesmo arquivo.

E o try/Catch responsável pela exceções, exemplo: Arquivo inexistente.

Você diz usar eles juntos como algo tipo:

try
{
    using (var leitor = new LeitorDeArquivo("contas.txt"))
    {
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();
    }
}
catch (IOException ex)
{
    Console.WriteLine("Exception do tipo IOException foi tratada.");
}

? Ou precisaria ter o finally? Pois acredito que se houver uma exceção, eu ainda precisarei fechar o arquivo, certo? Pois não executará até o fim do using {} caso aconteça (não haverá o Dispose). Adaptando o código acima, imagino assim:

LeitorDeArquivo leitor = null;
try
{
    using (leitor = new LeitorDeArquivo("contas.txt"))
    {
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();
    }
}
catch (IOException ex)
{
    Console.WriteLine("Exception do tipo IOException foi tratada.");
}
finally
{
    if (leitor != null)
        leitor.Dispose();
}

Sim, usar os 2 juntos, igual ao seu primeiro código.

try/catch - Estará com o cargo de tratar as exceções, exemplo: O arquivo "contas.txt" não existe e etc...

using - Estará com o cargo de liberação dos recursos da classe que lê arquivo. Então, após passar pelas chaves do using, será executado automaticamente a liberação dos recursos daquela classe através do método Dispose().

Obs: Lembrando, ao usar o using a classe deve implementar a interface IDisposable, que neste caso é a sua classe "LeitorDeArquivo".

try
{
    using (var leitor = new LeitorDeArquivo("contas.txt"))
    {
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();
        leitor.LerProximaLinha();

    } //Dispose da classe LeitorDeArquivo será executado aqui
}
catch (IOException ex)
{
    Console.WriteLine("Exception do tipo IOException foi tratada.");
}

Então mesmo que ocorra uma exceção no bloco using, no caso, execução das linhas leitor.LerProximaLinha(), vai acabar acontecendo o Dispose() do leitor mesmo assim, é isso?

Isso mesmo.

solução!

Fiz um exemplo besta para exemplificar.

Caso 1:

O StreamWriter cria um arquivo e escreve nele, então criei uma exceção que é tentar dividir um número por zero, isso irá lançar uma exceção, que será tratada no catch, após o tratamento tento acessar o arquivo criado, como não utilizei o dispose(), irá dar outra exceção.

        static void Main(string[] args)
        {
            int zero = 0;
            string pathFile = @"teste.txt";

            try
            {
                StreamWriter stw = new StreamWriter(pathFile, true);

                stw.WriteLine("Inserindo texto no arquivo");

                //Exceção proposital
                var resultado = 10 / zero;

            }
            catch (Exception ex)
            {
                //Aqui vc faz o tratamento da exceção, estou colocando uma mensagem apenas para exemplo...
                Console.WriteLine($"Exceção: {ex.Message}");
            }

            //Dará outra exceção
            var file = File.ReadAllText(pathFile);

            Console.ReadLine();


        }

Caso 2 :

Coloquei o using, nisto terá o tratamento da exceção de divisão, mas não ocorre a outra exceção, pois o using usou o Dispose() da classe StreamWriter automaticamente.

        static void Main(string[] args)
        {
            int zero = 0;
            string pathFile = @"teste.txt";

            try
            {
                //Using para liberar os recursos do streamWriter
                using (StreamWriter stw = new StreamWriter(pathFile, true))
                {

                    stw.WriteLine("Inserindo texto no arquivo");

                    //Exceção proposital
                    var resultado = 10 / zero;

                }

            }
            catch (Exception ex)
            {
                //Aqui vc faz o tratamento da exceção, estou colocando uma mensagem apenas para exemplo...
                Console.WriteLine($"Exceção: {ex.Message}");
            }

            //Irá ler todas as linhas do arquivo
            var file = File.ReadAllText(pathFile);

            Console.ReadLine();

        }

Espero ter ajudado... Testa ai e me fala se entendeu rs

Testei e compreendi hehe. Muito obrigado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software