LA.NET [EN]

Jul 21

Back to the basics: more on casting

Posted in Basics      Comments Off on Back to the basics: more on casting

I’ve already mentioned casting several times before, but I guess I’ve jumped over several basic features associated with that operation. Since this is a basics series, I should have probably explained casting instead of assuming that everyone knows how it works. So, I’ll go back and use this post to present some features associated with casting in C#. By default, the CLR allow us to cast an object to its type or to any of its base types. If you’re using C#, then you don’t need to do anything to cast an object to any of its base types. Take a look at the following code:

class A { }
class B : A { }
class Program {
    static void Main(string[] args){
        var b = new B();
        A a = b;
    }
}

The example is simple: we have two types, where one type (B) extends the other (A). As you can see, we can cast the variable b to the type A without using any special syntax. C# will also let you go from an A to a B (but only if that A is-a B). Take a look at the following snippet:

var a = new A();
var b = new B();
A anotherA = b; //ok
B anotherB = (B) anotherA; //also ok
B stillAnotherB = (B) a;//oops: InvalidCastException

As you can see, “going” from A to B is possible, but only when we’re talking about an instance of type B (or derived from B). The CLR will always ensure at runtime that the cast works and it ends up throwing an exception when that cast is not possible (and when you don’t define a conversion operator that allows the conversion between those types).

Why does the CLR enforces this rule? One of the corner stones of the CLR is type safety. In practice, this means that at runtime the CLR always knows the type of each instance of an object. If the CLR allowed casts without enforcing these rules, then  you could end up with unpredictable code that could cause security breaches in an application. I’m not sure if you’ve noticed but a type can’t spoof another type at runtime because the method that returns the type of an instance (GetType) is not virtual. Since it’s not virtual,you cannot override,so casting an object to Object and calling the GetType method over that instance will always return an object’s true type (even in those cases where you use the new keyword to “redefine” a method). Here’s some code that illustrates this technique:

class A { }
class B : A {
    public new Type GetType(){
        return typeof (A);
    }
}
class Program {
 static void Main(string[] args){
  var b = new B();
  Console.WriteLine(((Object)b).GetType());//prints DemoProj.B
  Console.WriteLine(b.GetType());//ATTENTION:prints DemoProj.A
 }
}

Do notice that if you don’t cast the variable to object (btw, this cast always succeeds), then you’ll end up getting a spoofed type. And that’s it. Stay tuned for more.