質問

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.

しかし、すべてがそうではないので、逆は真実ではありません ASを考慮することができます Bs。これは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(), 、すべての動物が犬ではないからです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top