Language: EN

csharp-conversion-tipos-cast

Convert between types with Cast in C#

Type conversion (also known as casting or coercion) is the process of transforming a value from one data type to another.

This may be necessary when working with different data types and a specific value needs to be treated as another type.

There are two main types of conversions in C#, implicit conversions and explicit conversions.

Implicit Conversions

Implicit conversions are those that the compiler performs automatically (without us having to do anything).

This occurs only when there is no risk of data loss, usually when the destination data type is larger than the source data type.

For example,

int integerNumber = 10;
long longNumber = integerNumber;

In this case, the variable integerNumber is implicitly converted to long and assigned to the variable longNumber.

This is the case because we have a variable of type int and we want to assign its value to a variable of type long, which is larger than int. Therefore, there is no risk, and C# will automatically perform the implicit conversion:

Explicit Conversions

Explicit conversion (also known as casting) is used when a data conversion cannot be performed automatically by the compiler. For example, because there is possible data loss, or because the compiler does not “dare” to do it on its own.

To perform an explicit conversion in C#, it is necessary to use the casting operator

(dataType)object

Where,

  • dataType: is the destination data type
  • object: is the object that you want to convert.

For example, if we have a variable of type double and we want to convert it to an int type, we need to perform an explicit conversion:

double decimalNumber = 3.14;
int integerNumber = (int)decimalNumber;

In this case, we use the casting (int) to convert the variable decimalNumber to int. It is important to note that, in this example, the decimal part of the original number will be lost.

Conversion between reference types

It is also possible to perform conversions between reference types (such as classes and interfaces). These conversions can be more complex and require knowledge of the type hierarchy we are working with.

Casting between different reference types should be done carefully, and only if we are sure that the conversion is valid.

If the conversion is not valid, it will cause a runtime error 💥

Conversion from base classes to derived classes

public class Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Animal sound");
    }
}

public class Dog : Animal
{
    public void Bark()
    {
        Console.WriteLine("Woof!");
    }
}

public class Program
{
    public static void Main()
    {
        Animal myAnimal = new Dog(); // Implicit conversion from Dog to Animal
        Dog myDog = (Dog)myAnimal; // Explicit conversion from Animal to Dog

        myDog.Bark(); // Output: Woof!
    }
}

In this example, myAnimal is implicitly converted to Animal when instantiated as Dog. Then, an explicit conversion from Animal to Dog is performed to access the specific method of the derived class Dog.

Using is and as operators

The is and as operators facilitate safe checking and conversion between reference types.

is Operator

The is operator is used to check if an object is of a specific type.

object obj = "Hello, World!";
if (obj is string)
{
    Console.WriteLine("obj is a string");
}

as Operator

The as operator attempts to convert an object to a specified type and returns null if the conversion fails.

object obj = "Hello, World!";
string str = obj as string;

if (str != null)
{
    Console.WriteLine("The conversion was successful: " + str);
}
else
{
    Console.WriteLine("The conversion failed");
}

User-defined conversion

C# allows the definition of custom conversions between types by overloading the implicit and explicit conversion operators.

User-defined implicit conversion

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

    public Celsius(float degrees)
    {
        Degrees = degrees;
    }

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

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

    public Fahrenheit(float degrees)
    {
        Degrees = degrees;
    }
}

public class Program
{
    public static void Main()
    {
        Celsius celsius = new Celsius(25);
        Fahrenheit fahrenheit = celsius; // Implicit conversion
        Console.WriteLine(fahrenheit.Degrees); // Output: 77
    }
}

User-defined explicit conversion

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

    public Celsius(float degrees)
    {
        Degrees = degrees;
    }

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

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

    public Fahrenheit(float degrees)
    {
        Degrees = degrees;
    }
}

public class Program
{
    public static void Main()
    {
        Celsius celsius = new Celsius(25);
        Fahrenheit fahrenheit = (Fahrenheit)celsius; // Explicit conversion
        Console.WriteLine(fahrenheit.Degrees); // Output: 77
    }
}

Practical examples

Let’s look at some examples of conversions between basic types.

Conversion from int to float

int integerNumber = 100;
float floatNumber = integerNumber; // Implicit conversion
Console.WriteLine(floatNumber); // Output: 100

Conversion from double to int

double doubleNumber = 123.456;
int integerNumber = (int)doubleNumber; // Explicit conversion
Console.WriteLine(integerNumber); // Output: 123 (the decimal part is lost)

Conversion from char to int

char letter = 'A';
int asciiCode = (int)letter; // Explicit conversion
Console.WriteLine(asciiCode); // Output: 65 (ASCII code of 'A')