[C#]Effective C# 條款三: 運算子is或as優於強制轉型


對C#而言,在做型別轉換時,撇開一些型別有提供Parse可供轉型外,通常我們有兩種選擇:一種是利用as運算子、一種則是強制轉型。作型別轉換時,應盡量採用as運算子來做轉型的動作,因為它比強制轉型安全,也具有較好的效能。



這邊讓我們直接來看個例子。假設今天我們寫一段程式,需將Object轉型為MyType。我們可以使用as運算子處理:




object o = Factory.GetObject();
MyType t = o as MyType;
if(t != null)
{
//轉型成功
}else{
//轉型失敗
}







也可以使用強制轉型來做:




try
{
object o = Factory.GetObject();
MyType t = (MyType)o;
if (t != null)
{
//轉型成功
}
else
{
//Null
}
}
catch
{
//轉型失敗
}









很明顯的,使用as運算子來做轉型,程式會較為簡單易讀,不需添加例外處理,在效能上自然也不會有額外的負擔。強制轉型在使用上除了需作例外處理,也需外加null的判斷(主要是因為null可轉為任意型態)。而as運算子轉型就只需要檢查轉型後是否為null即可。



as運算子只能用於參考類型,不能應用於值類型(除非是Nullable的值類型)。像下面的程式就無法通過編譯器的編譯:




object o = Factory.GetObject();
int i = o as int;





這是因為值類型不可為null導致(因若o無法轉型為整數,值類型也不可為null,其值無從填入i)。像這樣的值類型轉換,我們就可以使用強制轉型來處理:




object o = Factory.GetObject();
int i = 0;
try
{
i = (int)o;
}catch {
//轉型失敗
}





好一點的寫法,可以搭配is運算子來避免異常的發生




object o = Factory.GetObject();
int i = 0;
if (o is int)
i = (int)o;





一般來說只有當不能使用as運算子作轉型動作時,才會考慮使用is運算子,不然多半會產生冗餘的程式碼。像是:




object o = Factory.GetObject();
MyType t = null;
if (o is MyType)
t = o as MyType;







由上述,我們可以得知,在型別轉換的抉擇上,最好遵循著一個順序:



image



值得一提的是,我們常用的foreach語法,由於要同時支援值類型與參考類型,內部的轉型是採用強制轉型,若轉型失敗會產生InvalidCastException例外。