多用as少用強制類型轉換

来源:https://www.cnblogs.com/gangzhucoll/archive/2020/02/18/12327574.html
-Advertisement-
Play Games

在 C 中存在一個名叫靜態類型檢查的機制,這個機制可以讓編譯器幫助我們把類型不服的用法找出來,從而使得應用程式在運行期間加少一些類型檢查的操作。但是有時候我們還是需要進行運行期類型檢查,比如我們在設計框架時將方法的參數類型定義為 object ,那麼這時我們就有很大的可能需要將 object 類型的 ...


在 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 更加具體更加詳細的類型,這主要歸功於它所返回的對象類型能夠和某種特定類型進行對比。

一、為什麼不用強制類型轉換

我們先來看一段代碼:

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 。同樣,先來看一小段代碼:

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

上面的這段代碼運行起來後將會報錯,為什麼呢?這是因為當 obj 不是 int 類型時返回的值是 null ,但是 int 類型無法接受 null 值。因此當指定類型不可接受 null 值時 as 無法進行類型轉換。

二、一個問題

下麵我們再思考一個問題,我們都知道 foreach 所針對的序列是非泛型序列它會在迭代過程中自動轉換,那麼 foreach 的類型轉換使用的是 as 呢還是強制類型轉換呢?
foreach 使用的時強制類型轉換,會把對象從 object 類型轉換成迴圈體所需要的類型,之所以使用強制類型轉換是因為 foreach 需要同時應對值類型和引用類型。

三、總結

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

本文由博客一文多發平臺 OpenWrite 發佈!更多文章掃碼關註“喵叔呦” 在這裡插入圖片描述


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 把x用八進位,十進位、十六進位的形式列印,把y用布爾值的形式列印:int x = 10;cout << oct << x << endl; //show octalcout << dec << x << endl; //show decimalcout << hex << x << endl; //... ...
  • 樹結構基礎 LCA c++ ……(省略,同LCA) int L[N], R[N];//每個子樹代表的區間 int tot;//總時間 //搜索整棵樹, 得到每個節點的深度 void dfs(int u, int f){//u: 一節點 f: 其節點的父親節點 L[u] = ++tot; dep[u] ...
  • [toc] 一.Java的基本數據類型介紹 | 類型 | 關鍵字 | 位數 | 預設值 | 取值範圍 | | : : | : : | : : | : : | : : | | 位元組型 | byte | 8 | 0 | 128~127 | | 短整型 | short | 16 | 0 | 32768~3 ...
  • springboot預設打包成jar,如果想打包成war,則需要做以下三步。 1.修改pom.xml文件 a.將jar改成war 1 <groupId>com.test</groupId> 2 <artifactId>01-springboot-HelloWorld</artifactId> 3 < ...
  • 下載cron包: go get github.com/robfig/cron 開啟一個定時: 根據cron表達式進行時間調度,cron可以精確到秒,大部分表達式格式也是從秒開始。 c := cron.New()預設從分開始,所以加上cron.WithSeconds(),保證定時按照表達式字面意思執行 ...
  • 1.工具類可以一次寫入多方多方調用,很大程度的節約開發時間得到想要的信息 這裡演示一個json介面的工具類(文件定義在App\Http\Controllers\Tools)中 <?php /** * Created by PhpStorm. * User: yly * Date: 2020/2/18 ...
  • 最近由於“武漢肺炎”疫情在家辦公,也沒閑著,最近學習了一下asp.net core mvc的一些網頁開發的的基礎知識,話不多說直接上教程! 一、創建Web應用程式 1)創建新項目 >找到 “ASP.NET Core Web 應用程式” 類型的項目(也可以模糊查詢:語言選擇c#,項目類型選擇Web): ...
  • 概述 ASP.NET Core可以說是處處皆註入,本文從基礎角度理解一下原生DI容器,及介紹下怎麼使用並且如何替換官方提供的預設依賴註入容器。 什麼是依賴註入 百度百科中對於依賴註入的定義: 控制反轉 (Inversion of Control,縮寫為 IoC ),是 "面向對象編程" 中的一種設計 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...