0

私は2つのクラスを持っています

 public class A
    {
        public A()
        {

        }
    }

    public class B:A
    {
        public B()
        {

        }
    }

Main のコードは次のとおりです。

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

ここで、1 行目は正常にコンパイルされ、2 行目は型キャスト エラーが表示されます。なぜこれが起こるのか。new B()new A()が呼び出されると、正確には何が起こりますか?

4

2 に答える 2

7

型の変数を宣言しB、それに型の値を割り当てようとしAました。Bあなたは一種のを定義しましたが、それはすべての'が'Aであるという意味ではありません。AB

このように考えてください:

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

Animal rex = new Dog()すべての犬が動物であるため、あなたはできますが、Dog fido = new Animal()すべての動物が犬であるとは限らないため、できません。

于 2010-09-06T12:19:58.587 に答える
2

新しいB()と新しいA()が呼び出されると、正確にはどうなりますか?

  • new A()Aヒープ上にタイプのオブジェクトを作成し、そのオブジェクトへの参照を返します。

  • new B()Bヒープ上にタイプのオブジェクトを作成し、そのオブジェクトへの参照を返します。

ここで、1行目は正常にコンパイルされ、2行目は型キャストエラーを表示しています。なぜこれが起こるのか。

Bサブクラスなので、型の参照が実行時型のオブジェクトを参照するAことは有効です。結局のところ、は単にの「特殊なケース」です。ABBA

Aただし、すべてのsをsと見なすことができるわけではないため、その逆は当てはまりませんBこれは、「実際の」非互換性がない場合でも、C#の安全な型システムによって厳密に適用されますが、そのような制限の理由は当然です。たとえば、Bプロパティを宣言したと想像してくださいpublic int Foo {get; set;}。これがどのように動作することを期待しますか:

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

これは明らかに非論理的です。参照が参照している実際のオブジェクトには、そのようなプロパティはありません。したがって、コンパイラはそのような構成を禁止します。

ここで、コードを次のように変更したと想像してください。

B b = (B)new A();

ここでは、作成されたオブジェクトが実行時にタイプの参照に割り当て可能になることをコンパイラーに通知していますB。これは正常にコンパイルされますが、アサーションが明らかに正しくないため、ランタイムInvalidCastExceptionがスローされます。

要約すると、C#の型システム(無視dynamicし、いくつかの特殊なケースがある場合)は静的安全Aです。具体的なインスタンスを、型であるかのように正常に処理することはできませんB

于 2010-09-06T12:19:05.577 に答える