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.
Conversión de int a float
int numeroEntero = 100;
float numeroFloat = numeroEntero; // Conversión implícita
Console.WriteLine(numeroFloat); // Salida: 100
Conversión de double a int
double numeroDoble = 123.456;
int numeroEntero = (int)numeroDoble; // Conversión explícita
Console.WriteLine(numeroEntero); // Salida: 123 (se pierde la parte decimal)
Conversión de char a int
char letra = 'A';
int codigoAscii = (int)letra; // Conversión explícita
Console.WriteLine(codigoAscii); // Salida: 65 (código ASCII de 'A')