Type casting error and constructor
I have two classes
public class A
{
public A()
{
}
}
public class B:A
{
public B()
{
}开发者_JAVA百科
}
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?
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.
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
.
精彩评论