“?”运算符除了检查 null 还做其他事情吗?
Does the "?." operator do anything else apart from checking for null?
如您所知,DateTime?
没有参数化的 ToString
(用于格式化输出),并执行类似
的操作
DateTime? dt = DateTime.Now;
string x;
if(dt != null)
x = dt.ToString("dd/MM/yyyy");
会抛出
No overload for method 'ToString' takes 1 arguments
但是,自从 C# 6.0 和 Elvis (?.
) 运算符,上面的代码可以替换为
x = dt?.ToString("dd/MM/yyyy");
哪个....有效!为什么?
因为 Nullable<T>
在 C# 中的实现方式使该结构的实例显示为可空类型。当你有 DateTime?
时,它实际上是 Nullable<DateTime>
,当你将 null
分配给它时,你在幕后将 HasValue
设置为 false
,当你检查null
,您正在检查 HasValue
,等等。?.
运算符只是以一种方式实现的,它取代了适用于引用类型和可空结构的相同习语。就像语言的其余部分使可空结构类似于引用类型一样(关于 null
-ness)。
简答:
DateTime?
只是 Nullable<DateTime>
的甜美语法,它不包含 DateTime
的属性和方法,而 是 Elvis 运算符适用于不可空 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#
对 Nullable<T>
有一个特定的参考 Elvis 运算符,使其return 值 不可为空的T 本身.
整个Elvis operator
的结果必须是Nullable
因此,如果你想收到一个非 string
值它必须是 Nullable<T>
或 ReferenceType
但这不会改变这样一个事实,即如果操作员已经设法获得 Nullable<DateTime>
值本身- returned 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");
如您所知,DateTime?
没有参数化的 ToString
(用于格式化输出),并执行类似
DateTime? dt = DateTime.Now;
string x;
if(dt != null)
x = dt.ToString("dd/MM/yyyy");
会抛出
No overload for method 'ToString' takes 1 arguments
但是,自从 C# 6.0 和 Elvis (?.
) 运算符,上面的代码可以替换为
x = dt?.ToString("dd/MM/yyyy");
哪个....有效!为什么?
因为 Nullable<T>
在 C# 中的实现方式使该结构的实例显示为可空类型。当你有 DateTime?
时,它实际上是 Nullable<DateTime>
,当你将 null
分配给它时,你在幕后将 HasValue
设置为 false
,当你检查null
,您正在检查 HasValue
,等等。?.
运算符只是以一种方式实现的,它取代了适用于引用类型和可空结构的相同习语。就像语言的其余部分使可空结构类似于引用类型一样(关于 null
-ness)。
简答:
DateTime?
只是 Nullable<DateTime>
的甜美语法,它不包含 DateTime
的属性和方法,而 是 Elvis 运算符适用于不可空 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#
对 Nullable<T>
有一个特定的参考 Elvis 运算符,使其return 值 不可为空的T 本身.
整个Elvis operator
的结果必须是Nullable
因此,如果你想收到一个非 string
值它必须是 Nullable<T>
或 ReferenceType
但这不会改变这样一个事实,即如果操作员已经设法获得 Nullable<DateTime>
值本身- returned 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");