Visual C# 8.0中引入了可空引用类型(Nullable reference type),通过编译器提供的强大功能,帮助开发人员尽可能地规避由空引用带来的代码问题。这里我大致介绍一下可空引用类型的基本内容。

刚开始接触这个语言特性的时候,可能会不太容易理解。引用类型本来不就是可以为空(null)的么,为啥还要特别地引入“可空引用类型”的概念呢?其实这是从编译器的角度要求开发人员在编程的时候就考虑某个变量是否有可能为空,从而尽可能地减少由空引用所带来的代码错误。

假设有如下类:

class Student
{
public Student(string name, DateTime dayOfBirth)
=> (Name, DayOfBirth) = (name, dayOfBirth); public string Name { get; set; } public DateTime DayOfBirth { get; set; } public string Notes { get; set; }
}

此类定义了一个“学生”实体的基本信息,为了简化起见,这里只列出了需要讨论的几个属性:

  • Name:学生姓名
  • DayOfBirth:学生生日
  • Notes:对学生信息的一些备注

假设我们有两个操作:在所有学生中,找出所有具有备注信息的学生,以及对所有学生按姓名排序,在C#中很容易使用Linq来实现:

var studentsHasNotes = students.Where(s => s.Notes.Length > 0);

以及:

var orderedStudents = students.OrderBy(s => s.Name);

到目前为止没啥问题,程序能够正常运行。然而仔细进行代码审查不难发现,在获取所有具有备注信息的学生的代码中(也就是上面第一段代码中),有可能出现空引用的异常,因为对于一个“学生”实体来说,它的Notes属性是有可能为null的。

现在我们打开“可空引用类型”这一语言特性,打开方式主要有两种:可以在项目级别,编辑csproj项目文件进行设置,也可以通过#nullable预编译指令来实现:

  • 编辑csproj项目文件,加入<Nullable>enable</Nullable>即可:

  • 通过#nullable预编译指令来实现,只需要在代码中需要的地方加入#nullable指令即可:

启用“可空引用类型”这一语言特性之后你会发现,在上面的Student类的构造函数处出现了一个警告,提示在构造函数执行完成时,不可为空的“Notes”属性需要有一个不为空的值,建议将其设置为可空的string类型。为什么编译器仅提示Notes有可能为空,而不是Name属性呢?因为构造函数中已经为Name赋值了,因此,对于任何一个Student的对象,Name不可能为空,而Notes则不然。

Name不可能为空?它不是string类型么?万一在代码中它为空了怎么办?别急,编译器是不会允许出现这种情况的:

在此,我们将Notes属性设置为string?类型,于是你会发现,位于构造函数上的警告信息已经没有了,因为我们允许Student对象可以没有Notes数据,但在“找出所有具有备注信息的学生”这一操作时,又会出现警告,提示说Notes有可能为空:

于是,你会发现,在启用了可空引用类型的语言特性后,我们就需要仔细考察Student类型中的每一个引用类型的属性,看它在实际应用中是否有可能为空,如果可能为空,则用可空引用类型来定义属性,之后编译器就会帮助你来分析哪些地方有可能存在空引用。

在上面的“找出所有具有备注信息的学生”例子中,如果你觉得Notes肯定不会为空,那么也可以使用“!”操作符来覆盖编译器的警告信息,比如:

现在流行的.NET开源框架基本上都已经支持了可空引用类型了,而且如果你是一名开源框架的开发人员,也强烈建议在你的框架中启用这一语言特性来尽可能地避免空引用问题。比如,如果你在代码中启用了可空引用类型特性,那么当你从Newtonsoft.Json的JsonConverter类继承时,你会发现,你必须使用可空引用类型的函数重载:

但如果你没有启用可空引用类型特性,那么当你从Newtonsoft.Json的JsonConverter类继承时,你会发现,重载函数的签名与以前一样:

好了,对于C# 8.0的“可空引用类型”大致就介绍这么多,相信应该已经基本上概括了它的要点和使用方式,在日常开发中应该够用了。

快速了解C# 8.0中“可空引用类型(Nullable reference type)”语言特性的更多相关文章

  1. [译]C#8.0中一个使接口更加灵活的新特性-默认接口实现

    9月份的时候,微软宣布正式发布C#8.0,作为.NET Core 3.0发行版的一部分.C#8.0的新特性之一就是默认接口实现.在本文中,我们将一起来聊聊默认接口实现. 众所周知,对现有应用程序的接口 ...

  2. C#中的值类型(value type)与引用类型(reference type)的区别

    ylbtech- .NET-Basic:C#中的值类型与引用类型的区别 C#中的值类型(value type)与引用类型(reference type)的区别 1.A,相关概念返回顶部     C#中 ...

  3. 【Unity3D】中的空引用 Null Reference Exception

    Null Reference Exception : Object reference not set to an instance of an object. 异常:空引用,对象的引用未设置到对象的 ...

  4. Nullable Reference Types 可空引用类型

    在写C#代码的时候,你可能经常会遇到这个错误: 但如果想避免NullReferenceException的发生,确实需要做很多麻烦的工作. 可空引用类型 Null Reference Type 所以, ...

  5. C# 8 - Nullable Reference Types 可空引用类型

    在写C#代码的时候,你可能经常会遇到这个错误: 但如果想避免NullReferenceException的发生,确实需要做很多麻烦的工作. 可空引用类型 Null Reference Type 所以, ...

  6. 迫不及待地体验了一把 C#8.0 中的可空引用类型(Nullable Reference)

    在我之前的一篇博客 NullReferenceException,就不应该存在! 中,我吐槽了 C# 中 null 的弊端以及避免 null 的方法:事实上这本都是现代高级语言中极力推崇的做法.Kot ...

  7. C#8.0可空引用类型的使用注意要点

    最近VS2019正式版发布了,装下来顺便试用了一下C#8.0,最大的看点应该就是可空引用类型了.不过C#8.0仍然处于Beta的状态,而且试用时也遇到了几个坑. 背景知识说明: 所谓的可空引用类型是指 ...

  8. C#3.0中的扩展方法

    在实际应用中,开发者完成代码的编译后,除非重新编译更改后的代码,否则开发者很难在原有代码中添加新的功能. 在C#3.0中,提供了一个扩展方法的新特性,可以使得开发者在编译后的程序集里边添加相关的方法, ...

  9. vue2.0中使用less

    第一部分:Less语言 与上一篇<vue2.0中使用sass>介绍的Sass语言一样,Less语言也是一种CSS的扩展语言,增加了变量.混合(minin).函数等功能,让CSS更易维护.方 ...

随机推荐

  1. CVE-2018-8120 提权

    经验证,诸多版本的Windows系统均存在该漏洞,文末同时附带一份利用该漏洞制作的提权工具,以供学习.经测试该工具支持Win2003 x32/x64.WinXP x32.Win7 x32/x64, W ...

  2. μC/OS-III---I笔记7---消息队列

    消息队列 任务之间仅仅靠信号量进行"沟通"是不够的,信号量可以标志事件的发生,却无法传递更多的数据,在需要任务间的数据信息传递时就绪要用到消息队列,传统我们一般在前后太系统中都是通 ...

  3. 翻译:《实用的Python编程》01_02_Hello_world

    目录 | 上一节 (1.1 Python) | 下一节 (1.3 数字) 1.2 第一个程序 本节讨论有关如何创建一个程序.运行解释器和调试的基础知识. 运行 Python Python 程序始终在解 ...

  4. 如何在 VSCODE 中高效使用 R 语言

    VSCODE 配置 R 一.功能特性展示 之前一直在用 Rstudio 来编写 R,也尝试用过 Pycharm 配置 R 环境. 但是由于现在需求要同时满足 Python,R 和网站要同时开发,为了避 ...

  5. zsh & git alias

    zsh & git alias $ code .zshrc $ code .bash_profile $ code ~/.oh-my-zsh # update changes $ source ...

  6. GMV (Gross Merchandise Volume)

    GMV (Gross Merchandise Volume) 商品总销量 https://www.zhihu.com/question/20146641 GMV=1销售额+2取消订单金额+3拒收订单金 ...

  7. c++ win32 关机 注销 重启

    #include <iostream> #include <Windows.h> #pragma comment(lib, "user32.lib") #p ...

  8. lms微服务框架介绍

    lms 框架简介 Lms是一个旨在通过.net平台快速构建微服务开发的框架.具有稳定.安全.高性能.易扩展.使用方便的特点.lms内部通过dotnetty实现高性能的rpc通信,使用zookeeper ...

  9. flask启动常见问题1:sqlalchemy.exc.ArgumentError: Mapper mapped class UserCode->data_system_user_email could not assemble any primary key columns for mapped table 'data_system_user_email'

    我的描述:当我编辑好flask以后,ORM映射数据库完成,启动项目时,发生现象: 解决: 看字面的意思是主键导致的错误,于是我查看了data_system_user_email的键参数配置,发现表没有 ...

  10. A study on ILC for linear discrete systems with single delay

    论文题目就是随笔的题目,以后的随笔的命名都是如此,特此说明. 论文的主要内容是偏理论研究的,引入了离散矩阵延迟指数函数,来处理具有单时滞线性离散系统.对于离散延迟矩阵指数函数其定义为: \[e_{m} ...