但下面的轉換只 會有一種行為,而不管st是什麼類型。
所以你應該選擇as來轉換對象, 而不是強制類型轉換。實際上,如果這些類型與繼承沒有關系,但是用戶自己定 義的轉換操作符是存在的,那麼下面的語句轉換將會得到一個編譯錯誤:t = st as MyType;現在你應該明白要盡可能的使用as,下面我們來討論不能使用as的時 候。as運算符對值類型是無效的,下面的代碼無法通過編譯:
object o = Factory.GetValue( );
int i = o as int; // Does not compile.
這是因為整形(ints)數據是值類型,並且它 們永遠不會為null。當o不是一個整形的時候,i應該取什麼值呢?不管你選擇什 麼值,它都將是一個無效的整數。因此,as不能使用(在值類型數據上)。你可以 堅持用強制轉化:
object o = Factory.GetValue( );
int i = 0;
try {
i = ( int ) o;
} catch
{
i = 0;
}
但是你並沒有必要這樣堅持用強制轉換。你可以用is 語句取消可能因轉換引發的異常:
object o = Factory.GetValue( );
int i = 0;
if ( o is int )
i = ( int ) o;
(譯注:is和as一樣,都是類型轉換安全的,它們在任 何時候都不會在轉換時發生異常,因此可以先用is來安全的判斷一下數據類型。 與as不同的時,is只是做類型檢測並返回邏輯值,不做轉換。)
如果o是 其它可轉化為整形的類型(譯注:但o並不是真正的整形),例如double,那麼is 運算操作會返回false。對於null,is總是返回false。
is只應該在你無 法用as進行轉換時使用。
另外,這是無意義的冗余:
// correct, but redundant:
object o = Factory.GetObject( );
MyType t = null;
if ( o is MyType )
t = o as MyType;
如果你寫下面的代碼,那麼跟上面一樣,都是冗余的:
// correct, but redundant:
object o = Factory.GetObject( );
MyType t = null;
if ( ( o as MyType ) != null )
t = o as MyType;
這都是低效且冗余的。如 果你使用as來轉換數據,那麼用is來做檢測是不必要的。只用檢測返回類型是否 為null就行了,這很簡單。
現在,你已經知道is,as和強制轉換之間的區 別了。而在foreach的循環中,是使用的哪一種轉換呢?
public void UseCollection( IEnumerable theCollection )
{
foreach ( MyType t in theCollection )
t.DOStuff( );
}
foreach循環是用強制轉換來完成把一個對象轉換成循環可用的 類型。上面的循環代碼與下面手寫的代碼(hand-coded)是等效的:
public void UseCollection( IEnumerable theCollection )
{
IEnumerator it = theCollection.GetEnumerator( );
while ( it.MoveNext( ) )
{
MyType t = ( MyType ) it.Current;
t.DOStuff( );
}
}