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 requiring a specific value 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 automatically performs without the need for explicit intervention by the programmer.
This is possible when there is no risk of data loss, or when the target data type is larger than the source data type.
For example, if we have a variable of type int
and want to assign its value to a variable of type long
, no explicit conversion is necessary, as C# will automatically perform the implicit conversion:
int integerNumber = 10;
long longNumber = integerNumber;
In this case, the integerNumber
variable is implicitly converted to long
and assigned to the longNumber
variable.
Explicit Conversions
Explicit conversion, also known as casting, is used when a data conversion cannot be performed automatically by the compiler. This may occur when there is a risk of data loss.
To perform an explicit conversion in C#, it is necessary to use the casting operator
(dataType)object
Where
- dataType is the target data type
- object is the object to be converted.
For example, if we have a variable of type double
and want to convert it to type int
, 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 decimalNumber
variable 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 a good understanding of type hierarchy and inheritance.
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 is performed from Animal
to Dog
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 text = obj as string;
if (text != null)
{
Console.WriteLine("The conversion was successful: " + text);
}
else
{
Console.WriteLine("The conversion failed");
}
User-defined conversion
C# allows defining custom conversions between types by overloading 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 see 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 (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')