c# 優化代碼的一些規則——使用is或as和強制類型轉換的區別[三]
- 2020 年 5 月 27 日
- 筆記
- c# 基礎(回憶錄)
前言
使用as和強制類型轉換的時候的區別是否僅僅是代碼形式上的區別。
答案是肯定不是的。
正文
看兩段代碼:
object o = Factory.GetObject();
Student student = o as Student;
if (student != null)
{
//dosomething
}
和
object o = Factory.GetObject();
Student student = o as Student;
try
{
Student student = (Student)o;
if (student != null)
{
//dosomething
}
}
catch (InvalidCastException e)
{
var str = e.Message;
}
問題來了,這兩者有什麼區別?
首先第二個裏面有一個損失性能的地方,就是try{}catch{}。
那麼可以肯定一點就是在程序健壯性相同的情況下,使用as最好。
問題又出現了,那麼什麼時候不能用as呢?或者as 和 強制類型轉換之間差別是什麼呢?
as 轉換的局限性在於,他只會做簡單的裝箱和拆箱工作,而不會去做一些類型轉換。
也就是說,如果待轉換的對象既不屬於目標對象,也不屬於派生出來的類型那麼是不能轉換的。
這裡就有人奇怪了,如果兩者都不屬於那麼轉換失敗正常啊。
怎麼說呢,請考慮下面兩種情況:
1.數值之間轉換,比如int轉long之類的。
2.自己實現轉換,如:implicit
這兩者as搞不定的。
比如說:
有一個child 類,想轉學生類。
這樣寫:
public class Child
{
public static implicit operator Student(Child child)
{
return new Student();
}
}
然後我來這樣寫:
object o = Factory.GetObject();
Student student = o as Student;
if (student != null)
{
//dosomething
}
GetObject為:
public static implicit operator Student(Child child)
{
return new Student();
}
這樣寫是不成功的。
圖我貼出來了。
那麼我這樣寫,是否能成功呢?
object o = Factory.GetObject();
try
{
Student student = (Student)o;
if (student != null)
{
//dosomething
}
}
catch (InvalidCastException e)
{
var str = e.Message;
}
遺憾的是,這樣寫也是失敗的。
那麼為什麼失敗呢?
C# 有一個編譯期和一個運行期。
而強制轉換髮送在編譯期。
也就是說它讀取的是object能不能轉換為Student,而不是在運行期的Child。
好的,那麼你可以這樣。
object o = Factory.GetObject();
var c = o as Child;
try
{
Student student = (Student)c;
if (student != null)
{
//dosomething
}
}
catch (InvalidCastException e)
{
var str = e.Message;
}
這樣是對的,但是對於編程學來說,誰會去這樣寫呢,在很多時候我們應該盡量避免裝箱和拆箱。
在此總結一下,那就是as 運行在運行期,而cast 在編譯期。
好的,as 完了後,看下is吧。
is 是遵守多態的,多態很好理解哈。
所以is 不是==的意思,而是是否是自己或者子類的意思。
如果你想要去得到具體的類型判斷,那麼請使用getType更為合適。
總結
使用as或者 強制類型轉換沒有定性的要求,看具體的方案,然後呢當可以使用as的時候盡量使用as,畢竟可以避免try catch這種消耗性能的東西。