多用as少用強制類型轉換

在 C# 中存在一個名叫靜態類型檢查的機制,這個機制可讓編譯器幫助咱們把類型不服的用法找出來,從而使得應用程序在運行期間加少一些類型檢查的操做。可是有時候咱們仍是須要進行運行期類型檢查,好比咱們在設計框架時將方法的參數類型定義爲 object ,那麼這時咱們就有很大的可能須要將 object 類型的參數先轉換爲其餘類型。咱們進行轉換時會有兩種方法可使用:一種是強制類型轉換,這種方法能夠繞過編譯器的類型檢查,另外一種是先經過 is 判斷操做是否合理,是否能夠轉換,而後再使用 as 運算符進行轉換,或者使用強制類型轉換。下面咱們就來說解一下爲何多使用 as 少使用強制類型轉換。安全

零、as and is

使用 as 進行類型轉換會比強制類型轉換更加安全,並且運行時效率更高。可是這裏有一點須要注意的是 as 和 is 運算符不會考慮用戶所定義的類型轉換,只有當運行期的類型與要轉換到的類型相符時才能順利進行。通常來講 as 類型轉換不多會出現爲了類型轉換而建立新的對象,只有在 as 運算符把裝箱值類型轉換未裝箱且能夠爲 null 的類型時纔會建立新對象。
is 運算符遵循多態原則,也就是說例如 變量 Husky(哈士奇)是 Dog 類型,而且 Dog 類型繼承自 Animal 類型,那麼 代碼段 husky is Animal 返回值就是 True 。所以咱們能夠利用這一特性來判斷某個對象是不是某個具體類型。固然咱們也可用經過 GetType 方法來查詢對象的運行期類型,這樣可使開發人員寫出比 as 和 is 更加具體更加詳細的類型,這主要歸功於它所返回的對象類型可以和某種特定類型進行對比。框架

1、爲何不用強制類型轉換

咱們先來看一段代碼:spa

try
{
    object obj = Factory.GetObject();
    Animal animal;
    animal = (Animal) obj;
    if (animal !=null)
    {
        // more code
    }
    // more code
}
catch (InvalidCastExcept ex)
{
    // more code
}

在上述代碼中咱們使用了強制類型轉換將 object 類型的變量轉換爲 Animal 類型,我相信部分開發人員在實際開發中都會這麼寫,這麼些也不爲過,可是這其中存在一個問題,開發人員須要處理兩個問題。首先程序若是沒法將變量 obj 轉換爲 Animal 類型將拋出 InvalidCastException 異常,所以咱們必須捕獲,其次在強制類型轉換時遇到 null 的時候並不會拋出異常,所以咱們還要判斷變量 animal 是否爲 null 。既然強制類型轉換有這個問題,那咱們該如何解決呢?這時咱們就能夠用到 as 和 is 運算符了,一樣咱們先看一下代碼:設計

try
{
    object obj = Factory.GetObject();
    if (obj is Animal)
    {
        Animal animal =  obj as Animal;
        // more code
    }
    else
    {
        // more code
    }
}

利用這種方法咱們首先判斷 obj 是否能夠轉換爲 Animal 類型,若是能夠就利用 as 運算符來轉換,反之執行其餘代碼。既不須要捕獲錯誤,也不須要強制轉換,減小了代碼量同時也減小了代碼出錯的機率。
as 運算符和強制類型轉之間有一個很大的區別,那就是如何對待用戶自定義的轉換邏輯。 as 和 is 運算符除了必須進行的裝箱和拆箱外,它不會執行其餘任何操做,也就是說 as 和 is 只會判斷帶轉換對象在運行期是什麼類型,並根據結果進行相應的處理。那麼若是帶轉換對象既不屬於目標類型也不屬於目標類型所派生出來的類型的話, as 操做就宣告失敗。強制類型轉換則否則,它有可能使用一些類型的轉換邏輯進行類型轉換,並且不只僅是用戶自定義的轉換邏輯,還包含了內置類型之間的轉換。可是要注意的是強制類型轉換能夠會形成信息丟失,例如從 long 強制轉換爲 short 。
在某些狀況下利用強制類型轉換從代碼上來看彷佛能夠轉換成功,但實際上卻轉換不成功。這時爲何呢?雖然強制類型轉換會把用戶自定義的轉換邏輯考慮進去,可是它只針對對象的編譯期類型,編譯期類型並非是基類型。例如帶轉換類型在編譯期是 object 類型,所以編譯器會將它看做 object ,這時若是進行強制類型轉換的話就會報錯。
前面說了那麼多使用 as 的好處,那麼在這一小節裏咱們就來講說在何時不能使用 as 和 is 。一樣,先來看一小段代碼:code

object obj =Factory.GetValue();
int num = obj as int;

上面的這段代碼運行起來後將會報錯,爲何呢?這是由於當 obj 不是 int 類型時返回的值是 null ,可是 int 類型沒法接受 null 值。所以當指定類型不可接受 null 值時 as 沒法進行類型轉換。對象

2、一個問題

下面咱們再思考一個問題,咱們都知道 foreach 所針對的序列是非泛型序列它會在迭代過程當中自動轉換,那麼 foreach 的類型轉換使用的是 as 呢仍是強制類型轉換呢?
foreach 使用的時強制類型轉換,會把對象從 object 類型轉換成循環體所須要的類型,之因此使用強制類型轉換是由於 foreach 須要同時應對值類型和引用類型。繼承

3、總結

在開發中咱們應該儘可能避免使用強制類型轉換,強制類型轉換在某些狀況下可能會出現開發人員預料以外的結果,使用 as 和 is 運算符能夠確保對象確實能夠進行類型轉換時纔給出答案,這樣能夠保證程序的正確性。圖片

本文由博客一文多發平臺 OpenWrite 發佈! 更多文章請掃碼關注公衆號:「喵叔呦」 在這裏插入圖片描述
相關文章
相關標籤/搜索