Type casting error and constructor
-
01-10-2019 - |
Question
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?
Solution
What exactly happens when new B() and new A() gets called?
new A()
constructs an object of typeA
on the heap and returns a reference to it.new B()
constructs an object of typeB
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 A
s can be considered B
s.
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
.
OTHER TIPS
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.