« Voltar
em .net c#

As diferentes formas de se fazer e tratar um cast.

Alguns dias atrás, escrevi sobre a diferença entre cast e convert.

Agora, vamos supor que eu tenha essas duas classes:

public class Animal  
{
//atributos e métodos de Animal
}

public class Cachorro : Animal  
{
//atributos e métodos de Cachorro
}

public class Gato : Animal  
{
//atributos e métodos de Gato
}

E que eu tenha um método qualquer que receba como parâmetro qualquer objeto que seja um animal:

public void MetodoQualquer(Animal pAnimal)  
{
}

Dentro desse método, por alguma razão, quero tratar essa variável pAnimal como um Cachorro.
Posso então fazer um cast, certo?

public void MetodoQualquer(Animal pAnimal)  
{
    Cachorro vCachorro = (Cachorro)pAnimal;
}

Mas e se o que vier dentro dessa variável pAnimal não for uma instância de Cachorro? Poderia ser um Gato, certo?
Nesse caso, uma InvalidCastException iria pipocar na linha que estamos fazendo o cast.

Bem, pra resolver isso temos algumas opções.
Podemos colocar o cast dentro de um bloco try/catch:

public void MetodoQualquer(Animal pAnimal)  
{
    try
    {
        Cachorro vCachorro = (Cachorro)pAnimal;
    }
    catch(InvalidCastException)
    {
        //trata a exceção
    }
}

Outra opção seria: antes de fazer o cast, verificar se o que está dentro da variável pAnimal é um Cachorro usando o is:

public void MetodoQualquer(Animal pAnimal)  
{
    if(pAnimal is Cachorro)
    {
        Cachorro vCachorro = (Cachorro)pAnimal;
    }
    //faz o que tem que fazer
}

Dessa forma nunca daria Exception, já que temos certeza que o que está dentro do pAnimal é um Cachorro.

Fazendo cast de uma forma diferente

Uma forma que o pessoal está menos acostumado a fazer cast(eu vejo menos, pelo menos) é usando o operador as.
Poderíamos fazer assim:

public void MetodoQualquer(Animal pAnimal)  
{
    Cachorro vCachorro = pAnimal as Cachorro;
}

Qual a diferença do as e do cast "normal"?

A diferença é que, caso caso o C# não consiga fazer o cast nesse caso(ou seja, se pAnimal não for um Cachorro) ele não irá lançar uma InvalidCastException.
Ao invés disso, o valor da variável vCachorro simplesmente será null.

Aí, nesse caso, antes de prosseguir com o código do método seria interessante verificar se a variável é diferente de nula:

public void MetodoQualquer(Animal pAnimal)  
{
    Cachorro vCachorro = pAnimal as Cachorro;
    if (vCachorro != null)
    {
        //faz alguma coisa
    }
}

Isso porque, se tentarmos trabalhar com a variável nula tomaremos na cabeça uma das Exceptions mais comuns do C#: A NullReferenceException.
Aquela que mostra a mensagem Object reference not set to an instance of an object, sabe?

Qual a diferença entre as duas formas então?

A performance do cast com "as" é melhor. É mais rápido.
Prefira fazer o cast assim se estiver desenvolvendo algo que precisa de alta performance.

Fora isso, a diferença é basicamente a vimos aqui: com o cast "normal", o C# tenta fazer o cast do objeto e, se não conseguir, lança InvalidCastException.
No cast usando "as", ele tenta fazer o cast e, se não rolar, devolve nulo pra gente sem lançar Exception.

Quando usar uma forma ou outra?

Bem, tirando o caso que comentei acima sobre a questão da performance, não existe um jeito correto de se fazer cast. Dependendo da sua necessidade, um ou outro vai se encaixar melhor.

Apenas lembre-se: se for usar o jeito "normal", certifique-se de tratar InvalidCastException ou verificar o tipo antes. Se for usar o "as", valide se o cast foi bem sucedido (:


Quer ganhar 15% de desconto pra gastar na Casa do Código e ainda ficar em dia com as minhas postagem e outras promoções e sorteios legais? Assina minha newsletter: http://gabsferreira.com/newsletter/ (:

Se quiser, curta minha página no Face também! O endereço é https://www.facebook.com/devgabsferreira

comments powered by Disqus