2010-12-21 57 views
16

我想知道爲什麼在C#中的一些石膏在編譯時檢查,而在其他情況下的責任傾倒在CLR。像上面一樣,這兩個都不正確,但以不同的方式處理。編譯時和運行時的鑄件C#

class Base { } 
class Derived : Base { } 
class Other { } 

static void Main(string[] args) 
{ 
    Derived d = (Derived)new Base();  //Runtime  InvalidCastException 
    Derived d = (Derived)new Other(); //Compile-time Cannot convert type... 
} 

在閱讀「深入C#」我找到關於這一主題的信息,其中作者日期說:
「如果編譯器的斑點,這實際上是不可能爲鑄造工作,它會觸發編譯錯誤 - 如果理論上允許,但在執行時實際上不正確,則CLR將拋出異常。「

是「理論」的意思是繼承層次連接(某些對象之間的另一種親和?),或者是編譯器的內部的公司嗎?

+1

偉大的問題。我在等待比我更開明的人提供解釋。 – 2010-12-21 13:08:30

回答

20
  • 上傳可以在編譯時檢查 - 類型系統保證轉換成功。
  • 在編譯時無法(一般情況下)檢查下轉換,因此它們總是在運行時檢查。
  • 無關的類型不能互相轉換。

編譯器只考慮靜態類型。運行時檢查動態(運行時)類型。 看着你的例子:

Other x = new Other(); 
Derived d = (Derived)x; 

靜態類型的xOther。這與Derived無關,因此在編譯時轉換失敗。

Base x = new Base(); 
Derived d = (Derived)x; 

靜態類型的x現在Base。類型Base可能的東西有動態類型Derived,所以這是一個垂頭喪氣。一般來說編譯器不能從靜態類型的x知道,如果它運行時類型爲BaseDerivedBase一些其他子類。因此決定是否允許轉換是留給運行時間的。

+2

+1:很好的解釋:) – LaGrandMere 2010-12-21 13:15:03

1

如果您的變量爲Base類型,則可以通過Derived構造函數在理論上構造,因此實際上是Derived類型的變量。在編譯時,編譯器並不打算在每個特定情況下判斷是否可能出現這種downcast(代表變量Base類型爲Derived類型的實體)。

你的樣品很簡單 - 你創建一個新的類,並投它的時候了。但是如果你從其他地方得到Base,例如,某種方法調用呢?編譯器不能「猜測」你的方法將返回什麼,因此不會拋出錯誤。

當您投下Other時,編譯器發現Other實際上不可能是Derived並引發異常。