Diferentes tipos de Cast en .Net

Advertencia: Este artículo esta principalmente destinado para principiantes de .Net.

Hace mucho tiempo que tenía ganas de explicar acerca de las diferentes formas de hacer casting en .net puesto que me he encontrado muchas veces con malos usos de las diferentes sintaxis provistas por el framework. Si bien en este post los ejemplos estan CSharp, lo mismo se aplica para Vb.Net.

Por qué necesito castear?

La definición de MSDN es la siguiente:

Dado que los objetos son polimórficos, es posible que una variable de un tipo de clase base contenga un tipo derivado. Para tener acceso al método del tipo derivado, es necesario volver a convertir el valor al tipo derivado.

Para simplificar los ejemplos voy a utilizar el siguiente dominio:

2009-09-20_1723 
(Tomé esta imagen de algún post de Fabio Maulo)

Caso 1: 100% de seguridad de su tipo derivado

Hay algunos casos donde tenemos 100% de certeza de que el objeto en la variable es un derivado del tipo al cual queremos castear. Por lo tanto se usa una conversión explicita de la siguiente forma:

Animal someAnimal = GetAnimal();
var reptil = (Reptil) someAnimal;
Console.WriteLine(reptil.BodyTemperature);

MAL:

Animal someAnimal = GetAnimal();
var reptil = someAnimal as Reptil;
Console.WriteLine(reptil.BodyTemperature);

A continuación voy a explicar por que esta mal, y para que se utiliza el operador “as”.

Caso 2: No tengo seguridad acerca del tipo derivado

Hacer una conversión explicita como se explico en el caso 1 producirá una excepción del tipo InvalidCastException en caso de que el objeto presente en la variable no sea derivado del tipo al cual quiero castear. Por lo tanto en caso de no conocer si es un derivado de dicho tipo, utilizaremos el operador “as” la particularidad de este operador es que en caso de no serlo el resultado es null. Por lo tanto, nunca se debería utilizar este operador sin la correspondiente validación que el resultado del casteo sea nulo;

Animal someAnimal = GetAnimal();
var reptil = someAnimal as Reptil;
if(reptil != null)
    Console.WriteLine(reptil.BodyTemperature);

MAL:

Animal someAnimal = GetAnimal();
if(someAnimal is Reptil)
{
    Reptil reptil = (Reptil) someAnimal;
    Console.WriteLine(reptil.BodyTemperature);
}

El problema de este código, es que estoy realizando dos operaciones de cast la primera para verificar si la variable es del tipo Reptil, y la segunda donde realizó el cast. Por lo tanto este código es mas costoso que el anterior y esto nos lleva al caso 3.

Caso 3: Necesito solamente saber si el objeto presente en una variable es de una clase derivada de un tipo

En algunos casos es necesario saber solamente si es un derivado de un tipo especifico, es decir, no necesito realmente una conversión.

Animal someAnimal = GetAnimal();
if(someAnimal is Reptil)
{
    Console.WriteLine("Reptil!");
}

MAL:

Animal someAnimal = GetAnimal();
if((someAnimal as Reptil) != null)
{
    Console.WriteLine("Reptil!");
}


Esto fue todo, si bien he visto algunos casos peores que los que he marcado como mal, quería exponer los mas frecuentes.

Nota: Según nos comenta Eber Irigoyen desde twitter, el último ejemplo es equivalente en términos de performance.


blog comments powered by Disqus
  • Categories

  • Archives