O que é uma exceção
Uma exceção é um erro em tempo de execução em um programa, que viola uma condição que não foi especificada para acontecer durante a operação normal. Um exemplo na prática é quando um programa tenta fazer a divisão por zero ou tenta escrever em um arquivo somente leitura. Quando isto ocorre, o sistema pega o erro e lança uma exceção.
Se o programa não provê código para tratar uma exceção, o sistema irá parar o programa. Por exemplo, o seguinte código lança uma exceção quando o programa tenta dividir por zero.
Listagem 1: Exemplo de código que gera exceção
int x = 5, y = 0, z;
z = x / y;
A exceção lançada quando este código é executado é a seguinte

Figura 1: Exceção gerada por tentativa de divisão por zero
O compilador tenta fazer uma divisão por zero, porém, este é um erro de execução, pois a parte sintática e semântica está correta, porém uma divisão por zero infringe a matemática, logo, o sistema tenta executar por estar tudo correto, mas os valores não são aceitos.
Try
O comando try permite designar blocos de código a serem guardados para exceções e fornecer código para lidar com eles se eles ocorrerem. O comando try consiste de três seções.
- Try
- Catch
- Finally
O bloco de código do try contém o código que será validado e caso tenha uma exceção não será executado.
O cláusula catch pode aparecer uma ou mais vezes abaixo na seção do try. Estes blocos são códigos que lançam a exceção dependendo de qual exceção é gerada pelo compilador.
O finally contém o código a ser executado sobre qualquer circunstância. Tendo sido lançada ou não uma exceção o finally é executado.
Abaixo pode ser visto a estrutura básica do comando try
Listagem 2: Estrutura do bloco try-catch-finally
try
{
}
catch(ArgumentNullException)
{
throw;
}
catch(Exception)
{
throw;
}
finally
{
}
O try e o catch são obrigatórios, porém, não é necessário ter mais de um catch para cada tratamento de exceção.
O exemplo de código de divisão por zero causa uma exceção. O código pode ser modificado para que a exceção possa ser tratada utilizando o comando try e fornecendo uma simples cláusula catch. Quando a exceção é lançada, ela utiliza o código que está no bloco do catch para avisar o usuário o que está acontecendo de modo amigável.
Listagem 3: Exemplo de tratamento de exceção
try
{
int x = 5, y = 0, z;
z = x / y;
}
catch(Exception)
{
throw;
}
O código acima tenta executar a divisão por zero e depois quando verifica que existe uma exceção, aborta o processo daquele trecho de código e lança a exceção contida no catch.
Classes de exceção
Existem diversos tipos de exceção que podem ocorrer em um programa. É definido um número de classes de exceção, cada uma representa um tipo específico. Quando isso ocorre, uma exceção é criada para o tipo do objeto. Com isto, cada catch pode saber especificamente qual exceção está sendo lançada e resolver o erro de modo específico para cada um.
Todas as classes de exceção assim como todas as outras do framework .net são derivadas de object, porém, a primeira classe da qual todas as exceções derivam é a classe System.Exception. Abaixo pode ser visto toda a hierarquia de classes de exceções.

Figura 2: Hierarquia das classes de exceção do .NET Framework
Como pode ser visto na figura acima, existem três grandes grupos: ApplicationException, SystemException e IOException. Todos eles contém diversas subclasses que cada uma identifica de modo mais específico o erro que deve ser lançado. Caso não tenham certeza de qual erro será lançado, os programadores estão acostumados a lançar um erro genérico que no caso seria a utilização da classe Exception.
Uma exceção contém diversas propriedades somente leitura que mostram informações sobre a exceção que causou o erro. Algumas delas podem ser vistas abaixo.
| Propriedade | Tipo | Descrição |
| Message | String | Esta propriedade contém uma mensagem de erro explicando a causa da exceção. |
| StackTrace | String | Esta propriedade contém a informação que descreve aonde a exceção ocorreu. |
| InnerException | Exception | Se a exceção foi lançada por outra exceção, esta propriedade contém a referência da antiga exceção. |
O Catch
A função da cláusula catch é lançar uma exceção. Existem três maneiras de se fazer isto.
Catch geral
Não tem uma lista de parâmetros e encontra qualquer tipo de exceção encontrada pelo bloco try. Exemplo.
Listagem 4: Exemplo de catch geral
catch
{
}
Apesar de poder aceitar qualquer exceção, neste caso não é possível determinar o tipo de exceção que causou o erro.
Catch específico
Pega o nome de uma classe de exceção como um único parâmetro e encontra qualquer exceção do tipo do parâmetro passado. Exemplo.
Listagem 5: Exemplo de catch específico
catch(NullReferenceException)
{
}
Utiliza o nome da classe passada como parâmetro para lançar erros específicos, fazendo com que os erros sejam mais bem tratados.
Catch específico com objeto
Inclui um identificador depois do nome da classe de exceção. O identificador atua como uma variável local no bloco catch e é chamado de variável de exceção. A variável de exceção faz referência a um objeto de uma exceção, e pode ser utilizada para acessar informações sobre o objeto. Exemplo.
Listagem 6: Exemplo de catch específico com objeto
catch(Exception ex)
{
}
Utilizando o objeto passado por parâmetro podem ser utilizadas informações sobre a exceção. Como por exemplo, utilizar as propriedades Message, StackTrace e InnerException. Com isso pode-se utilizar estes dados para ter informações importantes para a resolução daquele determinado problema.
O Finally
Se um fluxo de controle de um programa entra em um comando try que tem um bloco finally, o bloco finally sempre irá ser executado.
Abaixo pode ser visto o fluxo geral do funcionamento de um try/catch/finally. Neste caso, se nenhuma exceção ocorrer dentro do bloco try, então no fim do bloco try irá pular para o bloco finally

Figura 3: Fluxo de execução dos blocos try-catch-finaly sem exceção
Agora neste caso, se uma exceção ocorrer em um bloco try, então o catch apropriado será executado e por último o finally.

Figura 4: Fluxo de execução dos blocos try-catch-finally com exceção
Criação de uma nova exceção
Para a criação de uma nova exceção é necessário criar uma classe que estenda da classe Exception (ou de outra classe de exceção mais específica), conforme sugere o exemplo abaixo.
Listagem 7: Definição de exceção customizada
class Excecao : Exception
{
public Excecao(string mensagem):base(mensagem)
{
//Construtor que chama o construtor da classe genérica
}
}
Para lançar uma exceção é necessário instanciar um objeto da classe de exceção e dar um throw (lançar) neste objeto, como o indicado abaixo.
Listagem 8: Lançamento de exceção customizada
try
{
int x = 5, y = 0, z;
z = x / y;
}
catch(Exception)
{
throw new Excecao("Um número não pode ser dividido por zero");
}
O exemplo mostra uma exceção lançada através de uma exceção criada. Isto é muito útil quando há a necessidade de se criar uma exceção para determinadas instruções referentes a alguma regra de negócio, por exemplo.
Então finalizamos aqui esse artigo. Até a próxima.