[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;
由上述,我們可以得知,在型別轉換的抉擇上,最好遵循著一個順序:
值得一提的是,我們常用的foreach語法,由於要同時支援值類型與參考類型,內部的轉型是採用強制轉型,若轉型失敗會產生InvalidCastException例外。