Dot Net For All

Type conversion in C#

Type Conversion

As we know C# is a type-safe language that I have discussed in my previous article. Type conversion is used by .net framework to achieve the type safety.Type safety can be decided by the compiler at compile time or at run time by the CLR. I will explain here both of these types of type safety with some more examples and a small exercise in the end. Moreover I will also discuss the as and is keywords used in the C#.

At runtime the CLR knows the type of an object. We can always discover the type of the object by calling the GetType() method. Since this method is non-virtual it is impossible for the type to spoof another type. Suppose we have an employee class as shown below.
//All types is already derived from System.Object  
public class Employee  
{  
}  
public class Manager:Employee  
{  
}  
public class SomeOtherType  
{  
}

Compile time type Checking
The preceding Manager class cannot override GetType() and return CEO as the class. There are basically two types of conversions that the compiler and CLR take care of in C#. They are implicit and explicit conversion. Implicit conversion takes place without any chances of data loss and that is why they are called safe explicit conversion.
Since I have defined a class Employee that implicitly derives from System.Object it is absolutely safe to create a variable of type object and assign it a reference of type Employee as shown below. In a more generalized term we can say that we can always have a variable of base type that can contain a reference of the derived type.

static void Main(string[] args)   
{  
   Object obj = new Employee(); // This is absolutely safe and compiler allows this  
   Employee emp = (Employee)obj; //This is also safe as compiler knows at the compile time that the obj contains a reference of type Empl   oyee  
   SomeOtherType otherType = (SomeOtherType)emp; //This is a compile type error for the same reason as compiler knows that obj is not a r   eference of SomeOtherType type  
}

Run time type Checking
There can be a scenario in which the compiler doesn’t know the type of the object that it is casting to at compile time. The example of that is explained here.
I have a function defined as in the following.

private static void ChangeDesignation(object o)  
{  
   Employee emp = (Employee)o; // At compile time the compile is not sure about the type of object o refers to that //allows the code to    build, but at run time  the CLR checks that o should be Employee type or type derived from //it, if not it throws InvalidCastException  
}

At compile time the compiler knows that o is the type of object and we are trying to explicitly cast o to Employee. That is fine since Employee derives from Object. Now if I want to pass an instance of type Manager in the same function, as shown below, the execution would work fine.

static void Main(string[] args)  
{  
   Manager manager = new Manager();  
   ChangeDesignation(manager); // This would work fine and it will create no problem at run time and in the function we can see that the    o is casted to the most base type only which is also safe  
   SomeOtherType otherType = new SomeOtherType();  
   ChangeDesignation(otherType);// The part of code will throw InvalidCastException at run time after it enters into the function  
}

Now in the next part of the code if I create an instance of SomeOtherType and pass as argument to the ChangeDesignation function the compiler would allow the code to compile but at run time we will get anInvalidCastException stating ‘Unable to cast object of type ‘TypeSafety.SomeOtherType’ to type ‘TypeSafety.Employee’.’ since CLR knows that the SomeOtherType is not derived from the Employee class. This part of code was to show the Run Time Type checking. If the CLR would have allowed the cast, there would not have been any type safety and the result would have been unpredictable, including an application crash and security breaches caused by the ability of types to easily spoof other types.An easy solution to prevent this type of run time exception would have been to declare ChangeDesignation with Employee type as parameter type instead of object type so that the compiler produces a compile-time error. An object as a parameter type has been used here in this example to show the run time type checking.

Casting with the C# is and as Operators
Apart from explicit casting that we have used in the ChangeDesignation method, is to check the valid casting using the is operator. The is operator checks whether an object is compatible with a given type and the result of the evaluation is a Boolean, whether true or false. The is operator never throws an exception. Kindly check the following code:

Object o = new Object();  
Boolean b1 = (o is object);//true  
Boolean b2 = (o is Employee);//false

If the object reference is null, the is operator always returns false since there is no object to check its type. The isoperator could have been typically used as in the following in the ChangeDesignation function:

if(o is Employee)  
   Employee emp = (Employee)o

The CLR’s type checking improves security, but it certainly comes at a performance cost, because the CLR must determine the actual type of the object referred to by the variable (o) and then the CLR must walk the inheritance hierarchy, checking each base type against the specified type (Employee). Since we need this kind of programming paradigm quite often, C# offers the as operator that simplifies our task and improves the performance bottleneck that is shown in the following code snippet:

Employee emp = o as Employee;  
if(emp != null)  
{  
   //use the emp variable  
}

The as operator in the preceding code checks if the o is compatible with the Employee type and if it is, as returns a non-null reference to the same object. if o is not compatible, it simply returns null without throwing any exception. If we use the preceding code without checking for null, it can be dangerous as shown below:

Object o = new Object();  
Employee e = o as Employee; //casts o to Employee which returns null  
e.ToString();// throws exception.

Now I would like to discuss a very interesting exercise that we would perform here and see if the code is fine or we will get a Run Time Error (RTE) or Compile Time Error (CTE) using the two classes shown below.

public class Base //base class  
{  
}  
public class Derived: Base //derived class  
{  
}  
static void Main(string[] args)  
{  
    Object o1 = new Object(); //Works fine  
    Object o2 = new Base(); //Works fine  
    Object o3 = new Derived(); //Works fine  
    Object o4 = o3; //Works fine  
    Base b1 = new Base(); //Works fine  
    Base b2 = new Derived(); //Works fine  
    Derived d1 = new Derived(); //Works fine  
    Base b3 = new Object(); //CTE as the b3 is a varible of Base type which derives from Object. We can have a instance of base type and reference of derived type  
    Derived d2 = new object(); //CTE for the same reason as above  
    Base b4 = d1; //Works fine  
    // Derived d3 = b2;// CTE we cannot simply convert a base class instance to derived type. we need to tell the compiler to explicitly convert to derviced type  
    //object. it should be Derived d3 = (Derived)b2  
    Derived d4 = (Derived) d1; //Works fine  
    Derived d5 = (Derived) b2; //Works fine  
    Derived d6 = (Derived) b1; //CTE for the reason that at compile time the compile is fine to cast the variable to base type, but at runtime the CLR checks that the b1 is an instance of type Base which contains a reference to Base type only and not the derived type  
    Base b5 = (Base) o1; //CTE for the same reason as above  
    Base b6 = (Derived) b2; //Works Fine  
}

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview