msdn05_capa.JPG

Clique aqui para ler todos os artigos desta edição

 

Tratamento de erros em .NET

por Marden Menezes

Um dos fantasmas que perseguem os desenvolvedores durante o desenvolvimento são os erros que ocorrem no programa. Se houver algum erro na escrita do código ou se quisermos, por exemplo, executar um método que ainda não tenha sido criado, o compilador nos avisará desse erro e nós poderemos consertá-lo antes de executar o programa. São os chamados erros “em tempo de compilação”. E quando os erros acontecem no momento em que o programa está sendo executado (os chamados erros “em tempo de execução”), o que fazemos?

A plataforma .NET oferece uma maneira estruturada de gerenciar e tratar erros através do mecanismo de Exceptions.

O que são Exceptions?

Exceptions são uma maneira estruturada e orientada a objetos de representar os erros. Esse mecanismo representa os erros como objetos e baseia-se em uma classe base chamada System.Exception, da qual derivam por herança todas as outras Exceptions. Veja algumas propriedades que a classe Exception oferece para facilitar o gerenciamento e reconhecimento de erros:

 

Propriedade

Descrição

Message

Propriedade somente leitura que contém um texto descritivo do erro.

InnerException

Caso a exceção tenha sido causada por outra exceção, essa propriedade retorna a referência a ela.

Source

O nome da aplicação ou do objeto que causou o erro.

StackTrace

Uma string que representa as chamadas da pilha no momento em que a exceção foi lançada.

Você pode criar uma Exception que herde a classe de qualquer outra Exception já existente no .NET, por exemplo, Exception, DivideByZeroException, FormatException, ApplicationException, OleDbException, etc.

Quando é lançada uma Exception?

Uma Exception é lançada sempre que ocorre um erro já definido (por exemplo, quando você tenta dividir um número inteiro por zero, chamando o DivideByZeroException). Caso você tenha criado uma Exception, informe quando ela será lançada, usando a palavra-chave throw. Veja na Listagem 1 como criar uma Exception e lançá-la no meio do código.

Listagem 1. Criação de uma Exception.

//código em C#

//Exception herdando de System.ApplicationException

using System

 

public class TextoInvalidoException : ApplicationException {

//algum código a ser modificado da Exception

}

// classe exemplo para lançar a Exception

public class App {

 

   public void RecebeTexto(string texto) {

       //Testa se o texto é vazio e lança a Exception

            if (texto == “”) throw new TextoInvalidoException();

   }

}

 

‘Código em Visual Basic .NET

‘Exception herdando de System.ApplicationException

 

Public Class TextoInvalidoException Inherits System.ApplicationException

‘algum código a ser modificado da Exception

End Class

 

‘classe exemplo para lançar a Exception

Public Class App

 

            Public Sub RecebeTexto(texto As String)

            ‘Testa se o texto é vazio e lança a Exception

               If texto = “” Then

                        Throw New TextoInvalidoException()

               End If

End Sub

End Class

Como tratar os erros?

Além de lançar os erros, é necessário tratá-los. Para isso, você deve usar o bloco try, catch, finally. O bloco try contém os códigos a serem testados e executados. Caso ocorra algum erro, o bloco catch será executado. O bloco catch tem uma estrutura parecida com o switch do C# e o Case do VB. Assim, podemos executar códigos diferentes dependendo da Exception gerada. Como nem sempre sabemos qual Exception pode ser lançada pelo código, podemos ter um bloco catch genérico que é chamado quando uma Exception é lançada. Normalmente, colocamos esse catch genérico no final do bloco para garantirmos que ele só será executado se nenhuma outra Exception do bloco for lançada. Essa hierarquia é fundamental para personalizar o erro.

O bloco finally é opcional e geralmente é usado para limpar recursos, fechar conexão com banco de dados, fechar arquivos, etc. O código do bloco finally é sempre executado, independentemente de ter ocorrido ou não um erro no bloco try.

É importante lembrar que, se você criar uma variável em algum dos blocos, ela só estará acessível neste bloco, ou seja, ela não poderá ser acessada no bloco finally se tiver sido criada no bloco try. Veja um exemplo na Listagem 2.

Listagem 2. Uso do bloco try, catch , finally em C# e VB .NET.

//código em C#

public void MetodoAuxiliar() {

  try

  {

    //código a ser testado

    string texto = Console.ReadLine();

    RecebeTexto(texto);

  }

  catch(TextoInvalidoException tie)

  { //será executado se ocorrer TextoInvalidoException

    Console.WriteLine(“Você digitou uma string vazia!”); 

  }

  catch(Exception ex)

  { //catch genérico pois é ativado por qualquer Exception

    Console.WriteLine(“Ocorreu um erro!”);

  }

  Finally

  {

     //esse código é sempre executado

    Console.WriteLine(“Sempre é executado!”);

  }

}

 

‘Código em Visual Basic .NET

Public Sub MetodoAuxiliar

  Try

    ‘código a ser testado

     Dim texto As String = Console.ReadLine()

     RecebeTexto(texto)

  Catch tie As TextoInvalidoException

     ‘será executado se ocorrer TextoInvalidoException

     Console.WriteLine(“Você digitou uma string vazia!”)

  Catch ex As Exception

     ‘catch genérico pois é ativado por qualquer Exception

     Console.WriteLine(“Ocorreu um erro!”)

  Finally

     ‘esse código é sempre executado

     Console.WriteLine(“Sempre é executado!”)

   End Try

End Sub

 

Veja um exemplo de código de tratamento de erros que lê os dados de uma tabela, preenche um objeto SqlDataReader e o mostra na tela. Note que as variáveis são criadas fora dos blocos, de modo que possam ser acessadas em qualquer parte dos blocos try, catch ou finally. Cabe ressaltar que o bloco finally é usado para fechar a conexão e o SqlDataReader (processos freqüentemente executados). Veja um exemplo na Listagem 3.

Listagem 3. Uso do bloco try, catch , finally em Banco de Dados.

//Código em C# - método que lê dados e mostra

//na tela através de um SqlDataReader

public void LerDados() {

    //cria as variáveis fora dos blocos

    SqlConnection conexao;

    SqlDataReader dr;

    try

    {

      conexao = new SqlConnection(“Data Source=(local);Initial Catalog=Northwind;User Id=sa;Password=senha”);

      //cria o objeto comando

      SqlCommand comando = conexao.CreateCommand();

      //define a string SQL do comando

      comando.CommandText = “Select * from Products”;

      //abre a conexão com o Banco

      conexao.Open();

      //preenche o SqlDataReader

      dr = comando.ExecuteReader();

      //lê dados do DataReader e mostra na tela

      while(dr.Read())

      {

         Console.WriteLine(dr[0].ToString());

      }

    }

    catch(SqlException sqlEx)

    {

      Console.WriteLine(“Erro no banco de dados”);

    }

    catch(Exception ex)

    {

      //código executado caso qualquer outra

      //exceção além de SqlException seja lançada

      Console.WriteLine(“Erro genérico”);

    }

    finally

    {

      //fecha a conexão e o DataReader

      dr.Close();

      conexao.Close();

    }

}

 

‘código em VB.NET - método que lê dados e mostra

‘tela através de um SqlDataReader

Public Sub LerDados()

  ‘cria as variáveis fora dos blocos

  Dim conexao As SqlConnection
  Dim dr As SqlDataReader

  Try

    conexao = New SqlConnection(“Data Source=(local);Initial Catalog=Northwind;User   Id=as;Password=senha”)

    Dim commando As SqlCommand = conexao.CreateCommand() ‘criando o objeto comando

    comando.CommandText = “Select * from Products”

    ‘define a string SQL do comando

    conexao.Open()  ‘abrindo a conexão com o Banco

    ‘preenche o SqlDataReader

    dr = comando.ExecuteReader()

    ‘lê dados do DataReader e mostra na tela

    While dr.Read

       Console.WriteLine(dr(0).ToString())

    End While

  Catch sqlEx As SqlException

    Console.WriteLine(“Erro no banco de dados”)

  Catch ex As Exception

    ‘código executado caso qualquer outra

    ‘exceção além de SqlException seja lançada

    Console.WriteLine(“Erro genérico”)

  Finally

    ‘fecha a conexão e o DataReader

    dr.Close()

    conexao.Close()

  End Try

End Sub

 

Conclusão

Vimos que a plataforma .NET nos oferece uma maneira mais estruturada de gerenciar erros com Exceptions. O fato de podermos criar erros customizados de acordo com a necessidade e de gerenciá-los com um código mais limpo usando o bloco “try, catch, finally” torna as Exceptions a melhor escolha.