c# - 什么是空的!声明是什么意思?

标签 c# c#-8.0 nullablereferencetypes

我最近看过以下代码:

public class Person
{
    //line 1
    public string FirstName { get; }
    //line 2
    public string LastName { get; } = null!;
    //assign null is possible
    public string? MiddleName {get; } = null;

    public Person(string firstName, string lastName, string middleName)
    {
        FirstName = firstName;
        LastName = lastName;
        MiddleName = middleName;
    }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
        MiddleName = null;
    }
}


基本上,我尝试挖掘c#8的新功能。其中之一是NullableReferenceTypes。实际上,已经有很多文章和信息。例如。 this article很好。
但我找不到有关此新语句null!的任何信息
有人可以为我提供解释吗?为什么我需要使用这个?
line1line2有什么区别?

最佳答案

理解null!含义的关键是理解!运算符。您之前可能已将其用作“非”运算符。但是从C#8.0开始,该运算符还可以用于控制Nullabilty的类型

在类型上使用!运算符是什么?

!运算符用于某种类型时,称为Null Forgiving Operator [docs]。它是在C#8.0中引入的



技术说明

典型用法

假设这个定义:

class Person
{
  public string? MiddleName;
}


用法是:

void LogPerson(Person person)
{
    Console.WriteLine(person.MiddleName.Length);  // WARNING: may be null
    Console.WriteLine(person.MiddleName!.Length); // No warning
}


此运算符基本上关闭编译器的空检查。

内部运作

使用此运算符告诉编译器可以安全地访问某些可能为空的内容。您表示打算在这种情况下“不关心”空安全性。

谈论null安全性时,变量可以处于2种状态。


可空-可以为空。
不可为空-不能为空。


从C#8.0开始,默认情况下所有引用类型都是不可为空的。

可以通过以下两个新的类型操作符来修改“可空性”:


! =从NullableNon-Nullable
? =从Non-NullableNullable


这些运算符基本上是彼此对应的。
编译器使用您使用这些运算符定义的信息来确保空安全性。

?操作员用法。


可空的string? x;


x是引用类型-因此默认情况下不可为null。
我们应用?运算符-使其可以为空。
x = null工作正常。

不可为空的string y;


y是引用类型-因此默认情况下不可为null。
y = null生成警告,因为您将空值分配给不应为空的值。



!操作员用法。

string x;
string? y = null;



x = y


非法! -Warning: "y" may be null
分配的左侧为不可为空,而右侧则为可为空。

x = y!


法律!
分配的左侧和右侧不可为空。
y!开始起作用,将!运算符应用于y,这使其不可为空。




  警告!运算符仅在类型系统级别关闭编译器检查-在运行时,该值可能仍为null。


这是一个反模式。

您应避免使用! Null-Forgiving-Operator。

在此操作员适合使用的情况下,存在有效的用例(在下面详细介绍),例如单元测试。但是,在99%的情况下,使用替代解决方案会更好。请不要在您的代码中拍打几十个!,只是为了静默警告。考虑一下您的原因是否真的值得使用。


  使用-但要小心。如果没有具体目的/用例,请不要使用它。


它抵消了编译器保证的空安全性的影响。

使用!运算符将很难发现错误。如果您有一个标记为不可为空的属性,则将假定您可以安全地使用它。但是在运行时,您突然遇到NullReferenceException并挠头。由于使用!绕过编译器检查后,值实际上变为null。

那么为什么这个运算符存在?


在某些情况下,编译器无法检测到可为空的值实际上是不可为空的。
遗留代码库迁移更容易。
在某些情况下,您根本不在乎某些东西是否为空。
使用单元测试时,您可能需要检查null通过时的代码行为。




具体回答您的问题。

那么null!是什么意思?

它告诉编译器null不是null值。听起来很奇怪,不是吗?

与上面示例中的y!相同。由于您将运算符应用于null文字,因此它看起来很奇怪。但是概念是相同的。

整理正在发生的事情。

public string LastName { get; } = null!;


该行定义了类型为LastName的名为string的不可为空的类属性。
由于它是不可为空的,因此从技术上讲,您不能为它分配null-显然。

但是,您只需执行-将null分配给LastName-使用!运算符。因为null!不为null-就编译器而言,它关注的是null安全性。

关于c# - 什么是空的!声明是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58116238/

相关文章:

c# - 内联函数定义

c# - 比较列表并返回不存在的对象

c# - 身份框架和自定义密码哈希器

c# - 在位图中创建 Windows 设置 (DPI) 独立文本

c# - "dotnet build"的 C#8 命令行编译器的最小安装

c# - 从另一个泛型方法调用一个 MaybeNull 泛型方法

c# - 将可空引用类型与泛型类型一起使用时收到警告