views:

63

answers:

2

I have two classes

 public class A
    {
        public A()
        {

        }
    }

    public class B:A
    {
        public B()
        {

        }
    }

and it the code in Main is as follows

    A oa = new B();
    B ob = new A();

Here line 1 compiles successfully while line 2 displays typecasting error. Why this happens. What exactly happens when new B() and new A() gets called?

+2  A: 

What exactly happens when new B() and new A() gets called?

  • new A() constructs an object of type A on the heap and returns a reference to it.

  • new B() constructs an object of type B on the heap and returns a reference to it.

Here line 1 compiles successfully while line 2 displays typecasting error. Why this happens.

Since B subclasses A, it is valid for a reference of type A to refer to an object of run-time type B. After all, B is simply a "special case" of A.

However, the converse is not true, because not all As can be considered Bs. Although this is strictly enforced by C#'s safe type-system even if there is no "real" incompatibility, the reasons for such restrictions are natural. Imagine, for example, that B declared a property public int Foo {get; set;}. How would you expect this to behave:

B ob = new A();
ob.Foo = 5;

This is clearly illogical: the real object that the reference is referring to has no such property. Consequently, the compiler prohibits such constructs.

Now imagine you changed your code to:

B b = (B)new A();

Here, you are telling the compiler that the object created, will, at run-time, be assignable to a reference of type B. This will compile fine, but since the assertion is clearly incorrect, a run-time InvalidCastException will be thrown.

To summarize, C#'s type system (if you ignore dynamic and a few special cases) is both static and safe: you will not successfully be able to treat a concrete instance of A as though it were of type B.

Ani
+7  A: 

You have declared a variable of type B, and then attempted to assign a value of type A to it. You have defined B to be a kind of A, but that doesn't mean that all A's are B's.

Think of it like this:

class Animal { }
class Dog : Animal { }
class Cat : Animal { }

You can do Animal rex = new Dog(), because all dogs are animals, but not Dog fido = new Animal(), because not all animals are dogs.

Blorgbeard