您好,登錄后才能下訂單哦!
本篇內容介紹了“C#中 As 和強制轉換的用法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
C#是一門強類型語言,一般情況下,我們***避免將一個類型強制轉換為其他類型,但有些時候難免要進行類型轉換。先想想究竟哪些操作可以進行類型轉換(先不考慮.NET提供的Parse),一般我們都有以下選擇:
使用as操作符轉換,
使用傳統C風格的強制轉型,
使用is來做一個轉換測試,然后再使用as操作符或者強制轉換。
正確的選擇應該是盡可能地使用as操作符,因為它比強制轉型要安全,而且在運行時層面也有比較好的效率(注意的是as和is操作符都不執行任何用戶自定義的轉換,只有當運行時類型與目標轉換類型匹配時,它們才會轉換成功)。
現在我們通過一個簡單的例子說明as和強制轉換之間的區別,首先我們定義一間獲取不同類型對象的工廠,然后我們把未知類型轉換為自定義類型。
object o = Factory.GetObject(); MyType t = o as MyType; if (t == null) { //轉換成功 } else { //轉換失敗 } object o = Factory.GetObject(); try { MyType t = o as MyType; if (t != null) { ////轉換成功 } else { ////轉換失敗 } } catch { ////異常處理 }
通過上述代碼我們發現as類型轉換失敗時值為null不拋出異常,但強制轉換如果轉換失敗會拋出異常所以我們要添加異常處理。
現在我們對as和強制轉換有了初步的了解,假設現在我們定義了一個抽象類Foo,然后Foo1繼承于它,并且再定義一個基類Logger,在Foo1中定義與Logger類型隱式轉換具體如下:
Foo1 myFoo; //// Inherits abstract class. Logger myFoo; //// base class. public class Foo1 : Foo { PRivate Logger _value; /// <summary> /// 隱式自定義類型轉換。 /// </summary> /// <param name="foo1"></param> /// <returns></returns> public static implicit Operator Logger(Foo1 foo1) { return foo1._value; } }
現在我們猜猜看以下的類型轉換是否成功(提示:從編譯和運行時類型轉換角度考慮)。
object myFoo = container.Resolve<Foo>(); //獲取未Foo1類型 try { Logger myFoo1 = (Logger)myFoo; if (myFoo1 != null) { Console.WriteLine("Covert successful."); } } catch { Console.WriteLine("Covert failed."); }
相信聰明的大家已經想出答案了,激動人心的時刻到了現在讓我們公布答案:轉換失敗拋出異常。
首先我們要從編譯和運行時角度來分析,在編譯時myFoo的類型為System.Object,這時編譯器會檢測是否存在自定義由Object到Logger的類型轉換。如果沒有找到合適轉換,編譯器將生成代碼檢測myFoo的運行時類型和Logger比較,由于myFoo的運行時類型為Foo1,而且我們自定義了由Foo1到Logger的類型轉換,估計這樣可以轉換成功了吧!然而恰恰沒有轉換成功,這究竟是什么原因呢?讓我們了解一下編譯器對于隱式類型轉換的原理吧。
通過我們發現用戶自定義的轉換操作符只作用于對象的編譯時類型,而非運行時類型上,OK現在讓修改一下代碼讓我們編譯器認識自定義類型中。
using (IUnityContainer container = new UnityContainer()) { UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); //獲取container名稱為CfgClass下的配置 section.Containers["CfgClass"].Configure(container); object tempFoo = container.Resolve<Foo>(); //獲取未Foo1類型 Foo1 myFoo = tempFoo as Foo1; //使用as先把object轉型為Foo1 try { Logger myFoo1 = (Logger)myFoo; if (myFoo1 != null) { Console.WriteLine("Covert successful."); } } catch { Console.WriteLine("Covert failed."); } Console.ReadKey(); }
現在類型可以轉換成功,這是因為編譯器使用了我們自定義的隱式轉換,由于myFoo這次的編譯類型為Foo1,編譯器首先查找是否存在Foo1和Logger自定義轉換類型,由于我們定義了一種由Foo1到Logger的隱式類型轉換所以轉換成功。
通過上述我們發現了as給我們帶來的好處,但是有一點我們要注意的是as只能用于引用類型不能用于值類型。那我就有個問題了在進行類型轉換之前如果我們并不知道要轉換的是值類型還是引用類型,那該怎么辦呢?現在是is登場的時候了。
bject tempFoo = container.Resolve<Foo>(); //獲取未Foo1類型 int myInt = tempFoo as int; //compile error
as不能用于值類型,這是因為值類型不能為null(注意:C#2.0中,微軟提供了Nullable類型,允許用它定義包含null值,即空值的數據類型)像這種情況我們應該使用強制類型轉換。
object tempFoo = container.Resolve<Foo>(); //獲取未Foo1類型 try { int myInt = (int)tempFoo; //轉換成功 if (myFoo1 != null) { Console.WriteLine("Covert successful."); } } catch { Console.WriteLine("Covert failed."); }
大家可以發現和我們之前使用的強制轉換類似,而且還有處理異常,現在修改一下我們代碼讓它更加簡潔實現如下:
object tempFoo = container.Resolve<Foo>(); //獲取未Foo1類型int i = 0; //值類型轉換 if (tempFoo is int){ i = (int) tempFoo;} object tempFoo = container.Resolve<Foo>(); //獲取未Foo1類型 Logger myFoo1 = null; //引用類型轉換 if (tempFoo is Logger) { myFoo1 = tempFoo as Logger; }
總結
as和強制轉換之間***的區別就在于如何處理用戶自定義的轉換。操作符 as和 is 都只檢查被轉換對象的運行時類型,并不執行其他的操作。如果被轉換對象的運行時類型既不是所轉換的目標類型,也不是其派生類型,那么轉型將告失敗。但是強制轉型則會使用轉換操作符來執行轉型操作,這包括任何內建的數值轉換(如:long轉int)。
一般情況我們應該先考慮使用as進行類型轉換,然后再考慮使用is,***才考慮使用強制轉換。
“C#中 As 和強制轉換的用法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。