为你的项目启用可空引用类型

为你的项目启用可空引用类型

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

SettingWarning Context StatusAnnotation Context Status
enableenabledenabled
warningenableddisabled
annotationsdisabledenabled
disabledisableddisabled

推荐直接使用 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 的时候就不能很好的工作,来看一个示例:

从上面的示例来看,在使用 importedList[i].Id/Title 之前已经使用了 Assert.NotNull(importedList[i]),理论上来说 importedList[i] 是不会为 null 的,但是编译器现在还没这么智能,还需要进一步的优化,Resharper 是可以检测出来的,对于测试项目你如果遇到这种情况可以禁用可空引用类型或者使用 annotations 配置,或者可以声明一个不可空的引用类型变量

最近改了两个项目,开始使用了可空引用类型,有需要可以参考一下,一个是类库项目,把原来使用 Jetbrains.Annotations 替换成了可空引用类型,可以参考:https://github.com/WeihanLi/WeihanLi.Npoi ,另一个是一个应用项目,可以参考:https://github.com/WeihanLi/DbTool/

最后想说,鉴于目前 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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/305660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有哪些编辑软件可以编辑c语言,可以推荐一个手机上最好用且免费的c语言编辑器吗?...

C4droid(又名C编译器)呗&#xff0c;一个既可以编辑&#xff0c;还可以运行C语言的手机编程软件&#xff0c;下面我简单介绍一下这个软件的安装和使用&#xff1a;1.首先&#xff0c;安装C4droid&#xff0c;这个直接在手机应用中搜索就行&#xff0c;如下&#xff0c;大概也就…

cas 4.2.7 官方手册_海城市地区,保险手册核验的简单流程

最近海城市社保正在进行保险手册的核验工作&#xff0c;据说是要将当地社保数据并网&#xff0c;由省社保机构监督管理。我们这个百万人口的县级市&#xff0c;核验工作只由一个部门在固定的办事大厅里完成&#xff0c;工作量也是相当大了。核验工作自9月末开始&#xff0c;已进…

在 C# 中生成代码的四种方式——包括.NET 5中的Source Generators

Microsoft在最新的C#版本中引入了Source Generator。这是一项新功能&#xff0c;可以让我们在代码编译时生成源代码。在本文中&#xff0c;我将介绍四种C#中的代码生成方式&#xff0c;以简化我们的日常工作。然后&#xff0c;您可以视情况选择正确的方法。在 .NET 中&#xff…

powercfg -h off_驭鲛记的主演会是谁?肖战关系特别好的艺人朋友呢?白敬亭和吴映洁有没有故事啊?高伟光是不是隐婚生子了?讲讲管h和马司令呗?...

近期后台提问的比较多&#xff0c;没被翻牌的小可爱们不要着急&#xff0c;我会尽力把大家的问题都照顾到&#xff0c;笔芯1. 扒扒&#xff0c;想知道华策驭鲛记的主演会是谁&#xff1f;主演还没定&#xff0c;女主在接触热巴&#xff0c;男主还没接触&#xff0c;这个戏明年才…

使用 C# 9 的records作为强类型ID - JSON序列化

使用 C# 9 的records作为强类型ID - 路由和查询参数在本系列的上一篇文章中使用 C# 9 的records作为强类型ID - 路由和查询参数&#xff0c;我们注意到强类型ID的实体&#xff0c;序列化为 JSON 的时候报错了&#xff0c;就像这样&#xff1a;{"id": {"value&qu…

HP LaserJet 1010卡纸解决方法

HP LaserJet 1010 系列打印机在打印过程中出现卡纸多由以下原因造成&#xff1a;1、纸盒里放入了过多的纸张或纸张位置没有放好。2、打印时使用的介质类型超出打印机的支持范围。常见卡纸位置&#xff1a;1 、硒鼓下方&#xff1b;2 、进纸口&#xff1b;3 、出纸口图 2&#x…

HP产品选件查询网站

[url]http://h18000.www1.hp.com/products/quickspecs/ProductBulletin.html#intro[/url][url]http://h18006.www1.hp.com/products/quickspecs/Division/12175.html[/url]所有的可通地此链接来查询DL380G5:[url]http://h18004.www1.hp.com/products/quickspecs/12477_div/1247…

如何使用 C# 中的 ValueTuple

Tuple 是一种数据结构&#xff0c;它由一个有序的、有限的、大小固定的、不可变的异构元素的序列组成&#xff0c;当我们说 Tuple 中的元素不可变&#xff0c;意味着其中的元素不能进行修改。ValueTuple 是在 C# 7 中被引入&#xff0c;它主要用来解决 Tuple 的两个问题。解决语…

tutte定理证明hall定理_人教社课本现低级错误?“爱因斯坦用相对论证明勾股定理”...

南方加客户端南方加客户端6月18日消息&#xff0c;近日&#xff0c;有网友在网上发帖称&#xff0c;人教版八年级下册数学自读课本中有关“爱因斯坦证明勾股定理”的内容疑似出现错误&#xff0c;此事引发网友关注&#xff0c;目前在社交平台上发酵。网友上传的课本图片据网友上…

在 “相对” 高薪面前,任何的喊冤叫屈都是苍白无力的

2021年刚开始&#xff0c;我的朋友圈就被一桩接着一桩的 “噩耗” 连番轰炸。1月1日&#xff0c;曾在《巴啦啦小魔仙》中饰演 “凌美琪” 的孙侨潞不幸去世&#xff0c;年仅25岁&#xff0c;死因是常年熬夜&#xff0c;再加上饮酒过量而导致的猝死。1月3日&#xff0c;我在网上…

在SQLSERVER企业管理器中如何创建触发器

下面将分别介绍在MS SQLServer 中如何用SQL Server 管理工具Enterprise Manager 和Transaction_SQL 来创建触发器。在创建触发器以前必须考虑到以下几个方面&#xff1a; CREATE TRIGGER 语句必须是批处理的第一个语句; 表的所有者具有创建触发器的缺省权限,表的所有者不能把该…

srv.sys蓝屏解决补丁_Win10 补丁 KB4556799 导致部分用户蓝屏死机和网络问题

IT之家5月26日消息 Windows 10 补丁 KB4556799对某些配置造成了许多新问题。除了音频问题&#xff0c;临时用户配置文件和FPS下降之外&#xff0c;Windows 10最新累积更新还导致某些用户出现蓝屏死机、崩溃和网络问题。与Windows 10更新一样&#xff0c;用户经常遇到一系列不同…

IdentityServer4(六)授权码流程原理之SPA

在【One by One系列】IdentityServer4&#xff08;四&#xff09;授权码流程中提过一句&#xff1a;“为了安全&#xff0c;IdentityServer4是带有PKCE支持的授权码模式”我们来回顾一下授权码流程&#xff08;A&#xff09;用户访问客户端&#xff0c;后者将前者导向认证服务器…

适合手机端的ckeditor样式_抖音运营干货(三):9款手机视频剪辑APP,让你轻松玩转后期!...

很多朋友想开始用手机拍视频&#xff0c;可能不知道如何剪辑&#xff01;本文将给大家介绍几款好用又方便的手机剪辑短视频工具&#xff0c;即便是零基础&#xff0c;用下面这些工具&#xff0c;你也可以轻松开始剪辑短视频。选择一款实用好用的剪辑工具很重要&#xff0c;工具…

来吧,是时候升级您的领英技术档案了

阅读此文需要2分钟&#xff08;文末有惊喜&#xff09;LinkedIn的应用之广超乎你的想象&#xff0c;包括社会招聘、公关、社群建设、销售、社交媒体营销&#xff08;包括社交广告&#xff09;以及员工宣传。LinkedIn档案不是一份简历&#xff0c;而是集客式营销&#xff08;inb…

c语言查单词小程序,【附源码】小程序初窥之简单查单词

新年假期百无聊赖&#xff0c;于是就看了一下微信小程序的开发方法&#xff0c;花了两天时间入了个门&#xff0c;这里记录一下。阅读之前&#xff0c;先确定你知道基本的 htmlcssjs 语法&#xff0c;这样就能更好地和我一样&#xff0c;以一个新手的视角来理解小程序。目标目标…

python连接mysql_Python爬虫进阶教程(八):MySQL 数据库连接

PyMySQL介绍PyMySql包含一个纯python的MySQL客户端库。PyMySQL的目标是成为MySQLdb的替代品&#xff0c;并在CPython、PyPy和IronPython上工作。版本要求python 下列之一CPython > 2.6 or > 3.3PyPy > 4.0IronPython 2.7mysql 下列之一MySQL > 4.1 (tested with on…

使用 gRPCurl 调试.NET 5的gPRC服务

介绍你用过 Curl 吗&#xff1f;这个工具允许你通过 http 来发送数据&#xff0c;现在有一个适用于gGRPC的工具&#xff0c;gRPCurl&#xff0c;在本文中&#xff0c;我将介绍如何下载安装这个工具&#xff0c;然后通过这个工具调试我们.NET 5上面的gGRC程序。安装 gRPCurlgRPC…

此 sqltransaction 已完成;它再也无法使用_手把手教你如何修眉毛,学会再也不用花钱去美容院了...

最近看到有网友在评论中询问怎么修眉毛&#xff0c;刚好小编我对修眉有一点研究&#xff0c;可能比不上专业修眉的&#xff0c;但是最少能看不是&#xff0c;今天拿出来献给大家&#xff0c;希望各位自己学会如何修眉毛&#xff0c;那样的话以后就再也不用花钱去美容院了。在此…

国产OS推广应从娃娃和体制内双管齐下

一直以来&#xff0c;国内桌面操作系统被微软垄断。究其根源&#xff0c;既有微软技术更成熟&#xff0c;软件生态丰富、服务完善、商业化水平更好等因素之外&#xff0c;也有老百姓习惯于使用Windows等因素。老百姓之所以习惯于Windows&#xff0c;则是因为破解版横行和微软早…