タイプキャストエラーとコンストラクター
-
01-10-2019 - |
質問
2つのクラスがあります
public class A
{
public A()
{
}
}
public class B:A
{
public B()
{
}
}
そして、それは主にコードが次のとおりです
A oa = new B();
B ob = new A();
ここでは、行1が正常にコンパイルされ、行2にタイプキャストエラーが表示されます。なぜこれが起こるのか。正確に何が起こるか new B()
と new A()
呼び出されますか?
解決
新しいb()と新しいa()が呼び出されると、正確に何が起こりますか?
new A()
タイプのオブジェクトを構築しますA
ヒープ上で、それへの参照を返します。new B()
タイプのオブジェクトを構築しますB
ヒープ上で、それへの参照を返します。
ここでは、行1が正常にコンパイルされ、行2にタイプキャストエラーが表示されます。なぜこれが起こるのか。
以来 B
サブクラス A
, 、タイプの参照に有効です A
ランタイムタイプのオブジェクトを参照します B
. 。結局、 B
単に「特別なケース」です A
.
しかし、すべてがそうではないので、逆は真実ではありません A
Sを考慮することができます B
s。これはc# 'sによって厳密に施行されていますが 安全な タイプシステムは、「実際の」非互換性がなくても、そのような制限の理由は自然なものです。たとえば、それを想像してみてください B
プロパティを宣言しました public int Foo {get; set;}
。これがどのように振る舞うと思いますか:
B ob = new A();
ob.Foo = 5;
これは明らかに非論理的です 本物 参照が参照しているオブジェクトには、そのようなプロパティがありません。したがって、コンパイラはそのようなコンストラクトを禁止します。
今、あなたがあなたのコードを変更したと想像してください:
B b = (B)new A();
ここで、あなたはコンパイラに、オブジェクトが作成した、 ランタイム, 、タイプの参照に割り当てることができます B
. 。これは正常にコンパイルされますが、アサーションは明らかに間違っているため、実行時間 InvalidCastException
投げられます。
要約すると、C#のタイプシステム(無視した場合 dynamic
そして、いくつかの特別なケース)は両方です 静的 と 安全な: :具体的なインスタンスを正常に扱うことはできません A
タイプのように B
.
他のヒント
タイプの変数を宣言しました B
, 、そしてタイプの値を割り当てようとしました A
それに。定義しました B
ある種のこと A
, 、しかし、それはすべてを意味しません A
そうです B
's。
このように考えてください:
class Animal { }
class Dog : Animal { }
class Cat : Animal { }
できるよ Animal rex = new Dog()
, 、すべての犬は動物だからですが、そうではありません Dog fido = new Animal()
, 、すべての動物が犬ではないからです。