foreach 為了同時支援實值型別與參考型別轉換,必須使用強制轉型。這使得 foreach 對任何目標物件都表現一致,但也因此可能拋出 InvalidCastException 例外。
IEnumerator.Current 回傳 System.Object,該物件未覆寫轉換運算子,故無法滿足我們先前的測試條件。(譯註:若集合儲存 SecondType,却用 MyType 進行 foreach,轉換會失敗,因迴圈中取得的是 System.Object,轉換行為等同 MyType t = (MyType)o;,此處 o 為 SecondType 但以 System.Object 形式存在。)
使用強制轉型的 foreach 不會在轉換時檢查集合中物件的實際執行階段型別,僅檢查 IEnumerator.Current 回傳的 System.Object 是否可轉換為迴圈宣告的型別(本例為 MyType)。
有時你需要知道物件的精確型別,而不僅是滿足可轉換的目標型別。as 運算子對任何衍生自目標型別的物件都會回傳非 null。GetType() 取得物件的執行階段型別,提供比 is 和 as 更嚴格的型別測試。其回傳的型別可與指定型別比較,以確認是否為所需型別。
若新增衍生自 MyType 的 NewType,儲存 NewType 物件的集合可在 UseCollection 中正常運作。若函數需對所有 MyType 執行個體運作,此做法不錯;但若僅針對精確的 MyType 物件,必須在迴圈內部進行精確型別比較。多數情況下,執行階段確定精確型別在物件相等性測試時最重要;其他比較中,is 和 as 提供的 isinst(IL 指令)比較在語意上已正確。
良好的物件導向實務建議避免型別轉換,但無法避免時,請用 C# 提供的 is 和 as 運算子清楚表達意圖。不同轉換方法有不同規則,is/as 在絕大多數轉換上語意正確,且當目標型別正確時總會成功。應選擇這些基本指令,而非可能產生意外副作用的強制轉型。