csharp-conversion-tipos-cast

Convertir entre tipos con Cast en C#

La conversión de tipos (también conocida como casting o coerción), es el proceso de transformar un valor de un tipo de dato a otro.

Esto puede ser necesario cuando se trabaja con distintos tipos de datos y se requiere que un valor específico sea tratado como otro tipo.

Existen dos tipos principales de conversiones en C#, conversiones implícitas y conversiones explícitas.

Conversiones implícitas

Las conversiones implícitas son aquellas que el compilador realiza automáticamente (sin necesidad de que tengamos que hacer nada).

Esto ocurre únicamente cuando no hay riesgo de pérdida de datos, generalmente cuando el tipo de dato de destino es más grande que el tipo de dato de origen.

Por ejemplo,

int numeroEntero = 10;
long numeroLargo = numeroEntero;

En este caso, la variable numeroEntero se convierte implícitamente en long y se asigna a la variable numeroLargo.

Esto es así porque tenemos una variable de tipo int y queremos asignar su valor a una variable de tipo long, este es más grande que int. Por tanto no hay riesgo, y C# realizará automáticamente la conversión implícita:

Conversiones explícitas

La conversión explícita (también conocida como casting), se utiliza cuando se requiere una conversión de datos que no puede realizarse automáticamente por el compilador. Por ejemplo, porque hay posible pérdida de datos, o porque el compilador no se “atreve” a hacerla solo.

Para realizar una conversión explícita en C#, es necesario utilizar el operador de casting

(tipoDato)objeto

Donde,

  • tipoDato: es el tipo de dato de destino
  • objeto: es el objeto que se desea convertir.

Por ejemplo, si tenemos una variable de tipo double y queremos convertirla a un tipo int, necesitamos realizar una conversión explícita:

double numeroDecimal = 3.14;
int numeroEntero = (int)numeroDecimal;

En este caso, utilizamos el casting (int) para convertir la variable numeroDecimal a int. Es importante tener en cuenta que, en este ejemplo, se perderá la parte decimal del número original.

Conversión entre tipos de referencia

También es posible realizar conversiones entre tipos de referencia (como clases e interfaces). Estas conversiones pueden ser más complejas y requieren conocer la jerarquía de tipos con la que estamos trabajando.

El cast entre tipos tipos referencia diferentes debe hacerse con cuidado, y solo si estamos seguros de que la conversión es válida.

Si la conversión no es válida, provocará un error en tiempo de ejecución 💥

Conversión de clases base a clases derivadas

public class Animal
{
    public void HacerSonido()
    {
        Console.WriteLine("Sonido de animal");
    }
}

public class Perro : Animal
{
    public void Ladrar()
    {
        Console.WriteLine("Guau!");
    }
}

public class Program
{
    public static void Main()
    {
        Animal miAnimal = new Perro(); // Conversión implícita de Perro a Animal
        Perro miPerro = (Perro)miAnimal; // Conversión explícita de Animal a Perro

        miPerro.Ladrar(); // Salida: Guau!
    }
}

En este ejemplo, miAnimal se convierte implícitamente a Animal al ser instanciado como Perro. Luego, se realiza una conversión explícita de Animal a Perro para acceder al método específico de la clase derivada Perro.

Uso de operadores is y as

Los operadores is y as facilitan la comprobación y conversión segura entre tipos de referencia.

Operador is

El operador is se utiliza para verificar si un objeto es de un tipo específico.

object obj = "Hola, Mundo!";
if (obj is string)
{
    Console.WriteLine("obj es una cadena");
}

Operador as

El operador as intenta convertir un objeto a un tipo especificado y devuelve null si la conversión falla.

object obj = "Hola, Mundo!";
string cadena = obj as string;

if (cadena != null)
{
    Console.WriteLine("La conversión fue exitosa: " + cadena);
}
else
{
    Console.WriteLine("La conversión falló");
}

Conversión definida por el usuario

C# permite definir conversiones personalizadas entre tipos mediante la sobrecarga de operadores de conversión implicit y explicit.

Conversión implícita definida por el usuario

public class Celsius
{
    public float Grados { get; set; }

    public Celsius(float grados)
    {
        Grados = grados;
    }

    public static implicit operator Fahrenheit(Celsius c)
    {
        return new Fahrenheit((c.Grados * 9 / 5) + 32);
    }
}

public class Fahrenheit
{
    public float Grados { get; set; }

    public Fahrenheit(float grados)
    {
        Grados = grados;
    }
}

public class Program
{
    public static void Main()
    {
        Celsius celsius = new Celsius(25);
        Fahrenheit fahrenheit = celsius; // Conversión implícita
        Console.WriteLine(fahrenheit.Grados); // Salida: 77
    }
}

Conversión explícita definida por el usuario

public class Celsius
{
    public float Grados { get; set; }

    public Celsius(float grados)
    {
        Grados = grados;
    }

    public static explicit operator Fahrenheit(Celsius c)
    {
        return new Fahrenheit((c.Grados * 9 / 5) + 32);
    }
}

public class Fahrenheit
{
    public float Grados { get; set; }

    public Fahrenheit(float grados)
    {
        Grados = grados;
    }
}

public class Program
{
    public static void Main()
    {
        Celsius celsius = new Celsius(25);
        Fahrenheit fahrenheit = (Fahrenheit)celsius; // Conversión explícita
        Console.WriteLine(fahrenheit.Grados); // Salida: 77
    }
}

Ejemplos prácticos

Vamos a ver algunos ejemplos de conversiones entre tipos básicos.