foreach須要用強制轉換來同時支持對值類型和引用類型的轉換 。通過選擇強制轉化,foreach循環就可以采用一樣的行為,而不用管(循環)目 標對象是什麼類型。不管怎樣,因為foreach循環是用的強制轉換,因些它可能 會產生BadCastExceptions的異常。
因為IEnumberator.Current返回一個 System.Obejct對象,該對象沒有(重寫)轉換操作符,所以它們沒有一個滿足(我 們在上面做的)測試。
(譯注:這裡是說,如果你用一個集合存放了 SecondType,而你又想用MyType來對它進行foreach循環,那麼轉換是失敗的, 原因是在循環時,並不是用SecondType,而是用的System.Object,因此,在 foreach循環裡做的轉換與前面說的:MyType t = ( MyType ) o;是一樣的錯誤 ,這裡的o是SecondType,但是是以System.Object存在。)
正如你已經知 道的,一個存放了SecondType的集合是不能在前面的函數UseCollection中使用 循環的,這會是失敗的。用強制轉換的foreach循環不會在轉換時檢測循環集合 中的對象是否具有有效的運行時類型。它只檢測由IEnumerator.Current返回來 的System.Object是否可轉換為循環中使用的對象類型,這個例子中是MyType類 型。
最後,有些時候你想知道一個對象的精確類型,而不僅僅是滿足當 前可轉換的目標類型。as運算符在為任何一個從目標類型上派生的對象進行轉換 時返回true。GetType()方法取得一個對象的運行時對象,它提供了比is和as更 嚴格的(類型)測試。GetType()返回的類型可以與指定的類型進行比較(,從而知 道它是不是我們想要的類型)。
再次考慮這個函數:
public void UseCollection( IEnumerable theCollection )
{
foreach ( MyType t in theCollection )
t.DOStuff( );
}
如果你添加了一個派生自MyType的新類NewType,那麼 一個存放了NewType類型對象的集合可以很好的在UseCollection 函數中工作。
public class NewType : MyType
{
// contents elided.
}
如果你想要寫一個函數,使它對所有MyType類型 的實例都能工作,上面的方法是非常不錯的。如果你只想寫一個函數,只對精確 的MyType對象有效,那你必須用精確的類型比較。這裡,你可以在foreach循環 的內部完成。大多數時候,認為運行時確定對象的精確類型是很重要的,是在為 對象做相等測試的時候。在大多數其它的比較中,由is和as提供的.isinst(譯注 :IL指令)比較,從語義上講已經是正確的了。
好的面向對象實踐告訴我 們,你應該避免類型轉換,但有些時候我沒別無選擇。當你無法避免轉換時,用 (C#)語言為我們提供的is和as運算符來清楚的表達你的意思吧。不同方法的強制 轉換有不同的規則。從語義上講,is和as在絕大多轉換上正確的,並當目標對象 是正確的類型時,它們總是成功的。應該選擇這些基本指令來轉換對象,至少它 們會如你所期望的那樣成功或者失敗;而不是選擇強制類型轉換,這轉換會產生 一些意想不到的副作用。
小結:翻譯的第三個原則。
今天下午在網上下載了電子版的書籍,因此 翻譯相對快一點點,至少不用自己輸入代碼了,那是很郁悶的事。繼續翻譯,爭 取在春節休假期間把所有的Items翻譯完。
我對書中所說的要注意的事項 基本上都自己測試一下,當然,如果是顯然正確的問題,就直接翻譯了,不做測 試。對於一些有疑點的地方,我盡可能的自己動手測試一下。繼續努力,相信後 面的翻譯會越來越快。
返回教程目錄