C#基礎 操作符之as

在程序中,進行類型轉換時常見的事,C#支持基本的強制類型轉換方法,例如

Object obj1 = new NewType();
NewType newValue = (NewType)obj1;

這樣強制轉換的時候,這個過程是不安全的,因此需要用try-catch語句進行保護,這樣一來,比較安全的代碼方式應如下所示:

Object obj1 = new NewType();
NewType newValue = null;
try
{
newValue = (NewType)obj1;
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}

但是上面的寫法在C#中已是過時的寫法,也是比較低效的寫法,比較高效且時尚的寫法是用as操作符,如下:

Object obj1 = new NewType();
NewTYpe newValue = obj1 as NewType;

安全性:
as操作符不會做過的轉換操作,當需要轉化對象的類型屬於轉換目標類型或者轉換目標類型的派生類型時,那麼此轉換操作才能成功,而且並不產生新的對象【當不成功的時候,會返回null】。因此用as進行類型轉換是安全的。
效率:
當用as操作符進行類型轉換的時候,首先判斷當前對象的類型,當類型滿足要求後才進行轉換,而傳統的類型轉換方式,是用當前對象直接去轉換,而且爲了保護轉換成功,要加上try-catch,所以,相對來說,as效率高點。
需要注意的是,不管是傳統的還是as操作符進行類型轉換之後,在使用之前,需要進行判斷轉換是否成功,如下:

if(newValue != null)
{
//Work with the object named “newValue“
}

但是,使用as操作符要注意以下幾點:
1、不用在類型之間進行類型轉化,即如下編寫就會出現編譯錯誤。

NewType newValue = new NewType();
NewTYpe1 newValue = newValue as NewTYpe1;

2、不能應用在值類型數據,即不能如下寫(也會出現編譯錯誤)

Object obj1 = 11;
int nValue = obj1 as int;

對於1.,可以用傳統的類型轉換方式完成:

NewTypeOne newTestOne = new NewTypeOne();
NewTypeTwo newTestTwo = (NewTypeTwo)newTestOne;

要想使上面的操作正確完成,在原有類型中增加類型轉換操作符函數,即需要完成類似如下的代碼:

public calss NewTypeOne
{
public static explicit operator NewTypeTwo( NewTypeOne obj1)
{
//Convert object into new type
}
}

對於2,在C#中可以使用is操作符,再加上老式的類型轉換操作,就可以安全完成轉換,要完成如上操作,正確的寫法如下:

Object obj1 = 11;
if(objTest is int )
{
int nValue = (int)obj1;
}

在C#中提供的很好的類型轉換方式總結爲:
Object => 已知引用類型——使用as操作符完成;
Object => 已知值類型——先使用is操作符來進行判斷,再用類型強轉換方式進行轉換;
已知引用類型之間轉換——首先需要相應類型提供轉換函數,再用類型強轉換方式進行轉換;
已知值類型之間轉換——最好使用系統提供的Conver類所涉及的靜態方法。

Is

Is:檢查對象是否與給定的類型兼容。例如,下面的代碼可以確定MyObject類型的一個實例,或者對象是否從MyObject派生的一個類型:

   if(obj is MyObject){}

如果所提供的表達式非空,並且所提供的對象可以強制轉換爲所提供的類型而不會導致引發異常,則 is 表達式的計算結果將是 true。

如果已知表達式始終是true或始終是false,則is關鍵字將導致編譯時警告,但是通常在運行時才計算類型兼容性。

注意:is運行符不能重載,is運行符只考慮引用轉換、裝箱轉換和取消裝箱轉換。不考慮其它轉換,如果用戶定義轉換。在Is運算符的左側不允許使用匿名方法。lambda表達式屬於例外。
     Object myObject = new Object(); 
     Boolean b1 = (myObject is Object);      true.  
     Boolean b2 = (myObject is Employee);    false.
     如果對象引用是null,is運算符總是返回false,因爲沒有可檢查其類型的對象。
is運算符通常像下面這樣使用:
    if (myObject is Employee)
     {
           Employee myEmployee = (Employee)myObject;
     }

在這段代碼中,CLR實際會檢查兩次對象的類型。is運算符首先覈實myObject是否兼容於Employee類型。如果是,那麼在if語句內部執行轉換型,CLR會再次覈實myObject是否引用一個Employee。CLR的類型檢查增加了安全性,但這樣對性能造成一定影響。這是因爲CLR首先必須判斷變量(myObject)引用的對象的實際類型。然後,CLR必須遍歷繼承層次結構,用每個基類型去核對指定的類型(Employee)。由於這是一個相當常用的編程模式,所以C#專門提供了as運算符,目的就是簡化這種代碼寫法,同時提升性能。

as:用於檢查在兼容的引用類型之間執行某些類型的轉換。

Employee myEmployee = myObject as Employee;

if (myEmployee != null)

{ }

在這段代碼中,CLR覈實myObject是否兼容於Employee類型;如果是,as會返回對同一個對象的一個非null 的引用。如果myObject不兼容於Employee類型,as運算符會返回null。

注意:as運算符造成CLR只校驗一次對象的類型。if語句只是檢查myEmployee是否爲null。這個檢查的速度比校驗對象的類型快得多。

as運算符的工作方式與強制類型轉換一樣,只是它永遠不會拋出一個異常。相反,如果對象不能轉換,結果就是null。所以,正確的做法是檢查最終生成的一引用是否爲null。如果企圖直接使用最終生成的引用,會拋出一個System.NullReferenceException異常。以下代碼對此進行了演示:


   Object o = new Object();        新建一個Object對象。

   Employee e = o as Employee;     將o轉型爲一個Employee

   e.ToString();                   訪問e會拋出一個NullReferenceException異常

備註:

as運算符類似於強制轉換操作。但是無法進行轉換,則as返回null而非引發異常。

示例:

expression as Type它等效於以下表達式,但是隻計算一次expression。

expression is Type ?(Type)expression : (Type)null

注意:as運算符只執行引用轉換和裝箱轉換。as運算符無法執行其它轉換,如果用戶定義的轉換,這類轉換應使用強制轉換表達式來執行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章