很多小伙伴在升级到Visual Studio 2022后发现,如果我们去新建一个.NET 6的项目,和原先VS2019中一摸一样的写法,却会出现CS8618 Non-nullable property或者其他可能为null的警告。虽然不影响代码的编译和运行,却让人心里不踏实。
这是因为VS2019除了.NET Core 3.x的项目类型,都是默认使用C# 7.3版本。而从C# 8.0之后,增加了对可为null类型的检查,旨在最大程度的减少运行时出现NullReference异常。
除非小伙伴们时刻关心C#版本更新内容,否则这个随着VS2022和.NET 6默认开启的新特性,可能带来的不是惊喜,反而有一点惊吓。
那么让我们来看看如何迎接这个新的改变。这个变化的主旨是希望代码中,尽可能不再有为null的情况。首先我们来看最常见的一个Warning,在属性声明的时候。

平平无奇的写法,其中却蕴藏着两个Warnings。这种的处理较为简单,给出明确的初始值即可。例如string.Empty。你可以觉得这是在脱裤子放屁,但是回过头想一想,在运行过程中FristName和LastName为“”的情况,一定是代码有意为之。而不是不知道哪里返回了一个null,且无意中赋值上去了。

第二种常见的情况,是我们获得了一个可为null类型的对象,然后直接使用了。下图中XDocument的Load方法返回了Xelement?类型的对象。如果我们不做null check,就会存在Warning的波浪线。

一般来说这里加个if判断,就完事了。至少这个方法本身算是交差了。就像Xdocument.Root这个属性一样。但是业务代码的设计,和基础框架API的设计在思路上是有区别的。业务代码在业务明确的情况下返回null,会造成一种无限套娃的微妙效果。就像下面这个,到了外面一层的使用方法,仍然要纠结于null check。

从这个方法看,如果我就是一定要获取Root对象,或者对Root对象做一些不可描述的事情。那么XML文件中root节点为空就是一个不可接受,完全错误的情况。我个人倾向直接throw NullReferenceException。

另一种相似的情况是,可空类型被作为参数在接下来的代码中使用。下面代码中的attribute在业务逻辑中,很有可能就不应该存在为null的情况。否则就是输入的源头有错误。

这时要么通过if来回避参数为null这个错误,要么干脆就把错误暴露出来。这里推荐使用ArgumentNullException的静态方法ThrowIfNull。比先写个if判断再throw的方式要省力得多。

Visual Studio通过代码静态分析来判断是否报告可为null的Warning。但是代码写起来是非常灵活的,所以有时候会有误报或者分析不出来的情况。比如下面这个例子。

明明已经对相同的对象做了null  check,但仍然会有Warning,这是因为Visual Studio并不认为这两段重复的代码是同一个东西。处理的方式也很简单,一是老老实实通过建立局部变量的引用来避免重复。

二是通过惊叹号(!)操作符告诉Visual Studio,我确信这里没有问题,别逼逼了。所以可以有下面这个写法。当然我个人并不推荐这么做,首先是这个写法不兼容之前低版本的C#,万一要做一个向低版本的移植或兼容就麻烦了。其次!操作符有些过度自信的感觉,它没有实际的意义,仅仅是关闭了这个Warning,颇有掩耳盗铃的意思。

以上就是今天想和大家讨论的,关于迁移到Visual Studio 2022和C# 10以后,遇到的可为null类型的问题。持续性的学习不是说要每个小版本都紧跟潮流,而是在每一次的新项目,新团队,新机遇到来的时候,即时地更新自己。一点浅见,抛砖引玉。

以下链接,是MS Learn上Windows开发的入门课程,单个课程三十分钟到60分钟不等,想要补充基础知识的同学点这里:

开始使用 Visual Studio 开发 Windows 10 应用

开发 Windows 10 应用程序

编写首个 Windows 10 应用

创建 Windows 10 应用的用户界面 (UI)

增强 Windows 10 应用的用户界面

在 Windows 10 应用中实现数据绑定

.NET 6学习笔记(4)——解决VS2022中Nullable警告的更多相关文章

  1. 【整理】解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function

    解决vue不相关组件之间的数据传递----vuex的学习笔记,解决报错this.$store.commit is not a function https://www.cnblogs.com/jaso ...

  2. Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  3. [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱

    在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...

  4. [原创]java WEB学习笔记39:EL中的运算符号(算术运算符,关系运算符,逻辑运算符,empty运算符,条件运算符,括号运算符)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  5. [原创]java WEB学习笔记38:EL 中的 11个 隐含对象 详解

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  6. [原创]java WEB学习笔记05:Servlet中的ServletConfig对象

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. Android(java)学习笔记110:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  8. Python学习笔记之从文件中读取数据

    10-1 Python 学习笔记:在文本编辑器中新建一个文件,写几句话来总结一下你至此学到的Python 知识,其中每一行都以“In Python you can”打头.将这个文件命名为learnin ...

  9. Docker学习笔记之-在CentOS中安装Docker

    上一节演示了如何 通过Xshell连接CentOS服务,链接:Docker学习笔记之-通过Xshell连接 CentOS服务 本节将演示 如何在CentOS中安装 Docker 第一步:更新系统包到最 ...

随机推荐

  1. Fail2ban 命令详解 fail2ban-regex

    fail2ban-regex是fail2ban提供的用来测试正则表达式的一个小工具,我们可以用它来测试正则表达式是否能够匹配到日志文件中的要禁止的IP行. fail2ban-regex默认情况下自动匹 ...

  2. 彰显个性│github和gitlab之自定义首页样式

    目录 一.个性首页 二.制作步骤 三.修改内容 一.个性首页 相信很多小伙伴在逛 github 和 gitlab 的时候 会发现很多开发者的首页异常的炫酷,如 https://github.com/c ...

  3. centos6搭建mysql

    目前CentOS6.5及一下版本基本上被官方给放弃更新了,但是考虑到忠实粉丝迟迟不肯放手,所以还留了入口但是非常有限 1.搭建mysql 可参照:https://blog.csdn.net/huang ...

  4. c++ 关于二分的STL 详解

    一.解释 以前遇到二分的题目都是手动实现二分,不得不说错误比较多,关于返回值,关于区间的左闭右开等很容易出错,最近做题发现直接使用STL中的二分函数方便快捷还不会出错,不过对于没有接触过的同学,二分函 ...

  5. Docker容器Nginx负载均衡配置、check及stub模块安装

    Nginx是一款高性能的HTTP和反向代理.负载均衡web服务器.本次在Docker容器中部署三个tomcat,Nginx代理三个tomcat服务(以下称节点)来模拟实现负载均衡效果,配置check模 ...

  6. ExtJS 同行表单域对齐有误处理办法

    更新记录 2022年5月29日 第一次编辑.使用的ExtJS版本:ExtJS 7.4 问题 原本都是显示正常的表单域,比如这些文本框.选择框都是正常. 在用户进行操作,然后显示验证提示后,明显出现了问 ...

  7. js中通过ajax调用网上接口

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  8. Java基础-并发篇

    3.1. JAVA 并发知识库 3.2. JAVA 线程实现/创建方式 3.2.1. 继承 Thread 类 ​ Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例. ...

  9. Redis基础与性能调优

    Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用. Redis支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hyperloglogs等. ...

  10. VisionPro · C# · 界面显示视觉结果图像

    程序界面通过 CogRecordDisplay 控件显示视觉运行结果图像. 按指定图像显示,代码如下: using System; using System.Windows.Forms; using ...