“.” 运算符除了检查 null 之外是否还执行任何其他操作

本文关键字:是否 执行 任何 操作 其他 运算符 null 检查 | 更新日期: 2023-09-27 18:32:28

您可能知道,DateTime?没有参数化ToString(用于格式化输出(,并且执行类似

DateTime? dt = DateTime.Now;
string x;
if(dt != null)
    x = dt.ToString("dd/MM/yyyy");

会扔

方法"ToString"没有重载需要 1 个参数

但是,由于 C# 6.0 和 Elvis (?.( 运算符,上面的代码可以替换为

x = dt?.ToString("dd/MM/yyyy");

哪。。。。工程!为什么?

“.” 运算符除了检查 null 之外是否还执行任何其他操作

因为Nullable<T>是在 C# 中实现的,使该结构的实例显示为可为 null 的类型。当你有DateTime?它实际上是Nullable<DateTime>,当你分配null时,你正在设置HasValue在幕后false,当你检查null时,你正在检查HasValue,等等。?.运算符的实现方式只是替换了适用于引用类型(也适用于可为空结构(的相同习惯用法。就像语言的其余部分一样,使可空结构类似于引用类型(关于null-ness(。

简短回答:

DateTime?只是Nullable<DateTime>的甜蜜语法,它不包含DateTime的属性和方法,而猫王运算符在不可为空的Nullable<DateTime>.Value上工作。


解释:

以下代码:

DateTime? dt = DateTime.Now;
string x;
if (dt != null)
    x = dt?.ToString("dd/MM/yyyy");

当反编译为 C# 5.0 时,会产生以下结果:

DateTime? nullable = new DateTime?(DateTime.Now);
if (nullable.HasValue)
{
    string str = nullable.HasValue ? nullable.GetValueOrDefault().ToString("dd/MM/yyyy") : null;
}

旁注:string似乎在if内声明是无关紧要的,因为在MSIL级别提升,并且由于稍后不会使用该值,因此反编译器将其显示为在该if范围内声明。

如您所见,由于DateTime?只是Nullable<DateTime>的甜蜜语法,C#Elvis 运算符Nullable<T> s 有一个特定的引用,使其返回值本身为不可为空的 T

整个Elvis operator的结果必须Nullable因此,如果要接收非string值,则必须是Nullable<T>值或ReferenceType,但这不会改变这样一个事实,即如果运算符设法获取了Nullable<DateTime>值本身 - 返回的DateTime不再Nullable<DateTime>

考虑:

DateTime? dt = DateTime.Now;
string x;
if(dt != null)
    x = dt.ToString("dd/MM/yyyy");

在这里dt DateTime?Nullable<DateTime>女巫不IFormatable,也没有ToString(string format)的方法。

所以它扔了。

现在考虑:

x = dt?.ToString("dd/MM/yyyy");

?.是句法糖,用于:

dt.HasValue ? dt.Value.ToString("dd/MM/yyyy"): null

在这里dt.Value是一个DateTime女巫IFormatable并有一个ToString(string format)方法。

最后,在 C# 5.0 中编写第一个代码的好方法是:

DateTime? dt = DateTime.Now;
string x;
if(dt.HasValue)
    x = dt.Value.ToString("dd/MM/yyyy");