C# 可空引用類型

来源:http://www.cnblogs.com/tdfblog/archive/2017/11/16/Nullable-Reference-Types-Preview.html
-Advertisement-
Play Games

可空引用類型是C 8.0計劃新增的一個功能,不過已經發佈了預覽版本,今天我們來體驗一下可空引用類型。 安裝 您必須下載Visual Studio 2017 15.5預覽版(目前最新發佈版本是15.4),下載地址:。 安裝Roslyn擴展預覽版本: 1. 下載並解壓 Roslyn_Nullable_R ...


可空引用類型是C#8.0計劃新增的一個功能,不過已經發佈了預覽版本,今天我們來體驗一下可空引用類型。

安裝

您必須下載Visual Studio 2017 15.5預覽版(目前最新發佈版本是15.4),下載地址:https://www.visualstudio.com/en-us/news/releasenotes/vs2017-preview-relnotes

安裝Roslyn擴展預覽版本:

  1. 下載並解壓 Roslyn_Nullable_References_Preview.zip [最新版本 11/15/17]
  2. 關閉所有運行的Visual Studio;
  3. 運行zip根目錄中的 .\install.bat 腳本(如果需要卸載擴展,可以運行.\uninstall.bat腳本);

語法與類型

在語法上,可為空引用類型與可為空值類型使用的語法是一致的,在類型後面追加 ? 即可。

class Person
{
    public string FirstName;   
    public string? MiddleName; 
    public string LastName;
}

我們都知道當初微軟在增加可為空值類型的時候,實際是在框架中增加了System.Nullable<>類型,您肯定會問,可為空引用類型以框架中又增加了什麼新的類型。

我們來看一個演示:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(typeof(string?).FullName);
        }
    }

輸出結果:

您是否覺得奇怪,怎麼輸出的是System.String,是的,其實微軟在框架中沒有加入任何類型,我們Person類型進行編譯後,再通過dotPeek進行反編譯,就明白到底發生了什麼。

反編譯後的結果:

    internal class Person
    {
        public string FirstName;
        [Nullable]
        public string MiddleName;
        public string LastName;
    }

只是在MiddleName欄位上增加了System.Runtime.CompilerServices.NullableAttribute標記。

我們來看一看屬性、參數、變數、返回值編譯之前與編譯之後的比對結果。

屬性

    // 編譯前:
    public string? MiddleName { get; set; }  
  
    // 編譯後:
    [Nullable]
    public string MiddleName { [return: Nullable] get; [param: Nullable] set; }

參數

    // 編譯前:
    public Person(string? middleName )
    {
        this.MiddleName = middleName;
    }

    // 編譯後:
    public Person([Nullable] string middleName)
    {
      this.MiddleName = middleName;
    }

返回值

    // 編譯前:
    public string? DoSomething()
    {
        return null;
    }

    // 編譯後:
    [return: Nullable]
    public string DoSomething()
    {
      return (string) null;
    }

變數

    // 編譯前:
    string? name;

    // 編譯後:
    string name;

這裡除了變數,其它的都使用了NullableAttribute標記進行的修飾。

它可以做什麼?

通過上面的章節,我們知道,可為空引用類型只是在參數、屬性、參數和返回值中使用NullableAttribute標記進行修飾,實際上對程式的正常運行沒有任何的影響。那麼它可以為我們做什麼呢?

表達意圖

在C#中不能表達這個變數、參數、欄位、屬性,返回值等可能為null或不能為null,可為空類型可以幫我們解決這個問題。

    class Person
    {
        public string FirstName;   // 不為null
        public string? MiddleName; // 可能為null
        public string LastName;    // 不為null
    }

這個類型的可以表示每一個人都應該 FristNameLastName ,但是不是每一個人都應該有 MiddleName

編譯器檢測

可為空引用類型的另一個好處是編譯器可以幫助我們檢測代碼,比如對於直接使用可為空引用類型的屬性,編譯器會發出警告

    void M(Person p)
    {
        p.FirstName = null;          // 1 WARNING: Cannot convert null to non-nullable reference。
        p.LastName = p.MiddleName;   // 2 WARNING: Possible null reference assignment.
        string s = default(string);  // 3 WARNING: Cannot convert null to non-nullable reference。
        
        if (p.MiddleName != null) 
        {
            WriteLine(p.MiddleName.Length); // ok
        }
        
         WriteLine(p.MiddleName!.Length); // ok
    }
    
    class Person
    {
        public string FirstName;     // 4 WARNING: Non-nullable field 'FirstName' is uninitialized.
        public string? MiddleName; 
        public string LastName;      // 5 WARNING: Non-nullable field 'LastName' is uninitialized.
    }

編譯器會幫我們做以下幾點檢測:

  1. 如果給非可為空引用類型賦null值或可為空引用類型的值,則會發出警告;
  2. 如果直接使用可為空引用類型,則會發出警告;
  3. 如果從來沒有給非可為空引用類型的屬性賦值,則會發出警告;
  4. 如果需要直接使用可為空引用類型,需要使用 ! 符號告訴編譯器,您已經確認過該值不可能為空。

當然這隻是編譯器的行為,可以禁用與之相關的警告提示。

總結

空引用類型是一個語法糖,只是在編譯器的層面幫我們發現可能發生的問題,對程式的正常運行沒有任何作用。

參考資料:


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

-Advertisement-
Play Games
更多相關文章
  • 1、下載安裝nginx 2、編輯nginx.conf文件 3、重啟或者啟動nginx 4、分別在172.100.10.21 和172.100.10.22 兩天機器人安裝配置apache+php或者nginx+php的環境 ...
  • sar命令常用格式 sar [options] [-A] [-o file] t [n] 其中: t為採樣間隔,n為採樣次數,預設值是1; -o file表示將命令結果以二進位格式存放在文件中,file 是文件名。 options 為命令行選項,sar命令常用選項如下: -A:所有報告的總和 -u: ...
  • 返回總目錄 本節包含3個手法: 1、Extract Method(提煉函數) 2、Inline Method(內聯函數) 3、Inline Temp(內聯臨時變數) Extract Method(提煉函數) 概要 你有一段代碼可以被組織在一起並獨立起來。 將這段代碼放進一個獨立函數中,並讓函數名稱解 ...
  • ASP.NET MVC程式設計自我感覺剛開始太難了,一個好好的頁面分成了好幾部分。剛開始沒有一點頭緒,只能按著源碼開始敲一遍,其中80%的代碼的含義都不知道啥意思,只能按著教材來一遍,開頭是非常痛苦,不知其然 , 更不知其所以然,出了問題就對著源碼看,看到底是哪段代碼的問題,就這樣敲了估計有大半個月 ...
  • Controller中的代碼如下var bingo = new Web1.Models.Bingo() { Title = "測試", desc = "嘻嘻", StarTime = DateTime.Now, EndTime = DateTime.Now.... ...
  • 在分析兩者之間的區別之前,我們先搞清楚這兩者的關係, TCP/IP協議簇 是一種網路控制協議,簡單點說就是一種網路協議,我們網路中的電腦就是通過這套協議簇來進行數據通信的。這套協議簇裡面包含了很多協議,比如說DNS,HTTP,ARP,ICMP等,UDP協議也是其中的一種。 關於TCP/IP協議簇詳 ...
  • 一、簡述 備忘錄,相信大家生活中都使用過,比如記筆記、手機備忘錄等等,這些都是記錄自己靈感時所想、定期內想做的事情,好像跑題了,說說我的備忘錄吧,我的備忘錄功能上也就是增刪改查的操作,另加到時提醒、語音播放內容,很簡單吧,但是實用,好了,想看設計點吧。 二、設計 1、資料庫設計 資料庫用的是SQLi ...
  • 題目:雞兔同籠。已知雞兔總頭數為y,總腳數為x,求雞兔各有多少只?解法一: ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...