2010-09-06 125 views
0

我有兩個類型鑄造誤差和構造

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()被調用時究竟發生了什麼?

回答

2

新的B()和新的A()被調用時究竟發生了什麼?

  • new A()構建在堆上A類型的對象,並返回對它的引用。

  • new B()在堆上構造一個類型爲B的對象並返回對它的引用。

這裏線1成功 編譯而線2種顯示類型轉換 錯誤。爲什麼會這樣。

由於B子類A,它是有效的A類型的引用指運行時類型B的對象。畢竟,B只是A的「特例」。

但是,反過來是不正確的,因爲不是所有的A s都可以被認爲是B s。儘管這是由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

7

您已聲明類型爲B的變量,然後嘗試爲其分配A類型的值。您已將B定義爲A,但這並不意味着所有A都是B's。

把它看成是這樣的:

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

你可以做Animal rex = new Dog(),因爲所有的狗都是動物,但不Dog fido = new Animal(),因爲不是所有的動物是狗。