主頁 > .NET開發 > 為你的專案啟用可空參考型別

為你的專案啟用可空參考型別

2021-01-18 06:03:05 .NET開發

為你的專案啟用可空參考型別

Intro

C# 從 8.0 開始引入了可空參考型別,我們可以為專案啟用可空參考型別來借助編譯器來幫助我們更好的處理代碼中的空參考的處理,可以避免我們寫很多不必要 null 檢查,提高我們的效率

Why

為什么我們要啟用可空參考型別呢,首先我們可以看一下 asp.net core 專案,asp.net core 的專案正在大量的使用可空參考型別,詳情可以參考:
https://github.com/dotnet/aspnetcore/issues/5680

Updating ASP.NET Core to use C# 8's nullable reference types would:

  1. Help ASP.NET Core libraries avoid null reference exceptions internally. It will help us find and prevent our bugs and increase our developer productivity
  2. Provide guidance to developers who are using ASP.NET Core about which APIs can accept and return a null reference and which APIs can't. This would improve the developer experience of using ASP.NET Core

主要分為兩方面,一方面是內部的代碼,對于內部代碼而言,使用可空參考型別我們可以借助編譯器清晰地了解一個變數是否會為 null ,不會為 null 的變數就不再需要進行空檢查了,另一方面是對于使用的代碼,對于使用啟用空參考型別的類別庫,編譯器可以提供更好的空檢查支持,開發者可以清晰地了解哪些 API 是允許為 null,哪些 API 是不允許為 null 的,對開發者更為友好

How

接著我們就來看一看如何為我們的專案啟用可空參考型別吧,微軟的檔案上提供了比較詳細的說明,詳細可以參考文末的參考鏈接

啟用可空參考型別只需要在專案檔案中添加 <Nullable>enable</Nullable> 即可,LangVersion 需要設定為 8 及以上,

Nullable 背景關系包含了兩個背景關系一個是 Nullable annotation context(支持 ? 表示可為空的參考型別),一個是 Nullable warning context(支持編譯器針對可空參考型別的警告)

Nullable 背景關系有 4 種配置,配置如下

  • enable
  • warnings
  • annotations
  • disable
Setting Warning Context Status Annotation Context Status
enable enabled enabled
warning enabled disabled
annotations disabled enabled
disable disabled disabled

推薦直接使用 enable 啟用可空參考型別,只啟用 annotation 背景關系,編譯器不會針對可空參考型別的檢查做出警告,意義就不太大了,只啟用 warning 背景關系,可以使用在不想在自己應用中啟用可空參考型別,可以嘗試這個配置,不配置 nullable 或者配置 disable 則可以完全禁用可空參考型別

除了針對 project 的 global 的配置之外,我們還可以在專案源代碼里通過 #nullable 來改變區域的可空背景關系配置,通過 #nullable restore 恢復默認的可空參考背景關系配置

  • #nullable enable: 設定 nullable annotation context 和 nullable warning context 為 enabled.
  • #nullable disable: 設定 nullable annotation context 和 nullable warning context 為 disabled.
  • #nullable restore: 恢復 nullable annotation context 和 nullable warning context 為專案默認的配置.
  • #nullable disable warnings: 設定 nullable warning context 為 disabled.
  • #nullable enable warnings: 設定 nullable warning context 為 enabled.
  • #nullable restore warnings: 恢復 nullable warning context 為專案配置
  • #nullable disable annotations: 設定 nullable annotation context 為 disabled.
  • #nullable enable annotations: 設定 nullable annotation context 為 enabled.
  • #nullable restore annotations: 恢復 annotation warning context 為專案配置

啟用可空參考型別之后,參考型別就不允許被設定為 null,如果要設定為 null,可以在型別后加一個 ? 設定為可空的參考型別如 string? ,或者使用 ! 讓編譯器允許賦值,如:string a = null!;(這也是我們需要注意的一個地方,可空參考型別只是編譯器的檢查,并不能夠嚴格的保證不會被賦值為 null,對于類別庫專案,如果public 的 API 期望的引數是不可空的參考型別,除了使用不可空參考型別外,還是需要保留 null 檢查)

Sample

首先可以看一個介面:

public interface IPropertyConfiguration<out TEntity, TProperty>
{
    IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(string title);

    IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(string? formatter);

    IPropertyConfiguration<TEntity, TProperty> HasColumnInputFormatter(Func<string?, TProperty?>? formatterFunc);
}

來看實作:

internal sealed class PropertyConfiguration<TEntity, TProperty> : PropertyConfiguration, IPropertyConfiguration<TEntity, TProperty>
{
    private readonly PropertyInfo _propertyInfo;

    public PropertyConfiguration(PropertyInfo propertyInfo)
    {
        _propertyInfo = propertyInfo;
        PropertyName = propertyInfo.Name;
        ColumnTitle = propertyInfo.Name;
    }

    public IPropertyConfiguration<TEntity, TProperty> HasColumnTitle(string title)
    {
        ColumnTitle = title ?? throw new ArgumentNullException(nameof(title));
        return this;
    }

    public IPropertyConfiguration<TEntity, TProperty> HasColumnFormatter(string? formatter)
    {
        ColumnFormatter = formatter;
        return this;
    }

    public IPropertyConfiguration<TEntity, TProperty> HasInputFormatter(
        Func<TEntity?, TProperty?, TProperty?>? formatterFunc)
    {
        InternalCache.InputFormatterFuncCache.AddOrUpdate(_propertyInfo, formatterFunc);
        return this;
    }
}

可以看到 HasColumnTitle 的引數中的 title 是不可空的參考型別,即使如此實作代碼里還是做了 null 檢查,而且可空參考型別在 throw new ArgumentNullException() 的時候也不會引發警告

警告示例

如果賦值 null 給一個不可為空的參考型別時,編譯器就會給出一個警告,示例如下:

在往一個不可空參考型別串列里中添加 null 時,編譯器也會給出一個警告:

如果一個可空的的參考型別變數沒有檢查 null 的時候,也會有警告:

從上圖中可以看出,使用 var 宣告變數的時候,會是一個可空的參考型別

More

使用可空參考型別可以一定程度上幫助我們減少不必要的 null 檢查,但是對于類別庫專案來說,該有的 null 檢查還是要有的

對于應用來說,借助可空參考型別也可以比較清晰地了解,哪些地方需要檢查 null,哪些地方不需要,可以提升代碼質量

對于 null 包容運算子 ! ,可以將一個可能 null 的物件賦值給不可空的參考型別變數,盡量不用使用,用了這個就是自己在代碼里埋雷,本來不會為 null 的變數、屬性也會出現 null 的情況,如果還沒有必要的 null 檢查,完全是自己給自己挖坑,

但是在使用程序中,感覺有些情況下還是不夠智能,在測驗專案中 Assert 的時候就不能很好的作業,來看一個示例:

image-20210117223138360

從上面的示例來看,在使用 importedList[i].Id/Title 之前已經使用了 Assert.NotNull(importedList[i]),理論上來說 importedList[i] 是不會為 null 的,但是編譯器現在還沒這么智能,還需要進一步的優化,針對這樣的情況,可以單獨宣告一個變數,使用 ! 來宣告一個不可空的參考型別,想要禁用測驗專案中的警告的話也可以設定 nullable 級別為 annotations 或者 disabled

最后想說,鑒于目前 asp.net core 正在大力采用可空參考型別,大家還是可以了解一下的

Reference

  • https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references
  • https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references
  • https://docs.microsoft.com/en-us/dotnet/csharp/nullable-migration-strategies
  • https://github.com/dotnet/aspnetcore/issues/5680
  • https://github.com/WeihanLi/WeihanLi.Npoi/pull/98
  • https://github.com/WeihanLi/DbTool
  • https://github.com/dotnet/samples/tree/master/csharp/NullableIntroduction/NullableIntroduction
  • https://stackoverflow.com/questions/54526652/when-to-null-check-arguments-with-nullable-reference-types-enabled
  • https://headspring.com/2020/06/02/applying-nullable-reference-types-in-fixie/

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/250006.html

標籤:.NET技术

上一篇:.NET探索平臺條件編譯

下一篇:.NET探索平臺條件編譯

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more