兩種轉換都失敗了。但是我告訴過你,強制轉化可以在用戶定義 的類型上完成。你應該想到強制轉化會成功。你是對的--(如果)它們跟像你想的 一樣是會成功的。但是轉換失敗了,因為你的編譯器為對象o產生的代碼是基於 編譯時類型。而對於運行時對象o,編譯器什麼也不知道,它們被視為 System.Obejct類型。編譯器認為,不存在System.Object類型到用戶類型MyType 的轉換。它檢測了System.Object和MyType的定義。缺少任意的用戶定義類型轉 換,編譯器(為我們)生成了用於檢測運行時對象o的代碼,並且檢測它是不是 MyType類型。因為對象o是SecondType類型,所以失敗了。編譯器並不去檢測實 際運行時對象o是否可以被轉換為MyType類型。
如果你使用下面的代碼段 ,你應該可以成功的完成從SecondType到MyType的轉換:
object o = Factory.GetObject( );
// Version three:
SecondType st = o as SecondType;
try {
MyType t;
t = ( MyType ) st;
if ( t != null )
{
// work with T, it's a MyType.
} else
{
// Report a null reference failure.
}
} catch
{
// report the failure.
}
你決不應該寫出如果糟糕的代碼,但它確實解決了一個很常 見的難題。盡管你決不應該這樣寫代碼,但你可以寫一個函數,用一個 System.Object參數來完成正確的轉換:
object o = Factory.GetObject( );
DOStuffWithObject( o );
private void DOStuffWithObject( object o2 )
{
try {
MyType t;
t = ( MyType ) o2; // Fails. o is not MyType
if ( t != null )
{
// work with T, it's a MyType.
} else
{
// Report a null reference failure.
}
} catch
{
// report the conversion failure.
}
}
記住,對一 個用戶定義類型的對象,轉換操作只是在編譯時,而不是在運行時。在運行時存 在介於o2和MyType之間的轉換並沒有關系,(因為)編譯器並不知道也不關心這些 。這樣的語句有不同的行為,這要取決於對st類型的申明:
t = ( MyType ) st;
(譯注:上面說的有些模糊。為什麼上面的代碼可能會有不 同的行為的呢?不同的什麼行為呢?主要就是:上面的這個轉化,是在編譯時還 是在運行時!如果st是用戶定義的類型,那麼上面的轉換是在編譯時。編譯器把 st當成為System.Object類型來編譯生成的IL代碼,因此在運行時是無法把一個 Object類型轉化為MyType類型的。解決辦法就是前面提到的方法,多加一條語句 ,先把Object類型轉換為SecondType,然後再強制轉化為MyType類型。但是如果 st是內置類型,那麼它的轉換是在運行時的,這樣的轉化或許會成功,看後面的 說明。因此,類似這樣的代碼:MyType m_mytype = (m_secondType as SecondType) as MyType;是不能通過編譯的,提示錯誤是無法在編譯時把 SecondType轉化為MyType,即使是重寫了轉換操作符。)