C# Type Conversions (Casting) Tutorial

In this tutorial we learn how to convert one data type to another with implicit, explicit (casting) and non-compatible type conversion. We also cover the Parse() function and the Convert class.

What is type conversion

Type conversion is the act of converting one type to another.

In C# we have three conversion types:

  • Implicit conversion.
  • Explicit conversion (also known as type casting).
  • Conversion between non-compatible types.

Implicit type conversion

Implicit conversions are done in a type-safe manner. If one type can safely be converted to another, it’s implicit, and the compiler will not raise an error.

For example, a byte can hold up to 255, and an int can hold up to 2 billion. We can implicitly convert a byte to an int because the value of 255 will always be able to fit into an int.

Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            byte b = 25;

            int i = b;

            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

An int is big enough to store any value that byte has, so we can easily copy a byte to an int.

In situations where the compiler is sure that no data loss will happen, it will allow implicit conversion.

Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 1;

            float f = i;

            Console.WriteLine(f);
            Console.ReadLine();
        }
    }
}

In the example above, the conversion is implicit because float is big enough to hold an int, and an int does not have decimal points with a precision greater than 7 digits.

Explicit type conversion (casting)

If the compiler knows that data loss may happen, it won’t allow implicit conversion.

For example, if we try to convert an int with a value greater than 255 to a byte, it will cause data loss because a byte can only store up to 255.

Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 300;

            byte b = i;

            Console.WriteLine(b);
            Console.ReadLine();
        }
    }
}

A byte is not big enough to store the value of 300 without data loss, so it can’t be implicitly converted and the compiler won’t allow it.

We need to explicitly tell the compiler that we’re aware of the data loss, and still want to go ahead with the conversion. Explicit type conversion is also known as casting.

When casting one type to another we specify the type between parentheses that we want to cast to.

Syntax:
(type) varToCast;
Example: cast int to byte
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 300;

            byte b = (byte)i;

            Console.WriteLine(b);
            Console.ReadLine();
        }
    }
}

The compiler will now allow the conversion and compile the code.

Example: cast float to int
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            float pi = 3.14f;
            int i = (int)pi;

            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

When the float converted into int it cut the decimal points completely, because an int doesn’t have decimal points.

Non-compatible type conversion

Sometimes we work with types that are not compatible, but we still need to convert them. We can’t cast a string into an int, it won’t compile.

Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "1";

            int i = (int)s;

            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

In situations like these we need a different mechanism of conversion.

C# provides us with two options:

  • Parse() method
  • Convert class

Convert primitive value types with Parse()

All the primitive value types have the Parse() method. It takes in a string as an argument between the parentheses and tries to convert it to the target type.

Syntax:
int.Parse( variable_to_convert )
Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "1";

            int i = int.Parse(s);

            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

In the example above, we parse the string “1” to an actual number 1.

Convert types with the Convert class

The Convert() class is part of the .NET framework and is defined in the System namespace.

It has a bunch of functions to convert one type to another. To use it we write the word Convert, followed by a dot operator, then the function we want to use to convert. Lastly we specify the data to convert as an argument between the parentheses.

Syntax:
using System; // Remember the System namespace

Convert.ToInt32( variable_to_convert )
Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "1";

            int i = Convert.ToInt32(s);

            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

While the conversion in the example above was successful, type overflow can still happen.

Example:
using System;

namespace TypeConversions
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "300";

            byte b = Convert.ToByte(s);

            Console.WriteLine(b);
            Console.ReadLine();
        }
    }
}

In the example above, overflow happens and the application crashes.

By default the Covert() class’ functions will check for overflow, which means we will receive an exception that we need to handle.

List of methods of the Convert class

The Convert class provides us with the following functions:

MethodDescription
ToBooleanConverts a type to a Boolean value, where possible.
ToByteConverts a type to a byte.
ToCharConverts a type to a single Unicode character, where possible.
ToDateTimeConverts a type (integer or string type) to date-time structures.
ToDecimalConverts a floating point or integer type to a decimal type.
ToDoubleConverts a type to a double type.
ToInt16Converts a type to a 16-bit integer.
ToInt32Converts a type to a 32-bit integer.
ToInt64Converts a type to a 64-bit integer.
ToSbyteConverts a type to a signed byte type.
ToSingleConverts a type to a small floating point number.
ToStringConverts a type to a string.
ToTypeConverts a type to a specified type.
ToUInt16Converts a type to an unsigned int type.
ToUInt32Converts a type to an unsigned long type.
ToUInt64Converts a type to an unsigned big integer.

Summary: Points to remember

  • We can convert types to other types. C# supports three conversion types.
    • Implicit conversion.
    • Explicit conversion (casting).
    • Non-compatible type conversion.
  • When one type is not compatible with another, we use a standalone function or a class with multiple conversion methods.
    • Primitive types can be converted with the Parse() function.
    • We can also use the Convert class to convert types.