代码之家  ›  专栏  ›  技术社区  ›  iuliu.net

“?.”操作符除了检查null之外还做其他什么吗?

  •  29
  • iuliu.net  · 技术社区  · 9 年前

    正如你可能知道的, DateTime? 没有参数化 ToString (为了格式化输出),并执行如下操作

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

    将投掷

    方法“ToString”的重载不接受1个参数

    但是,自从C#6.0和猫王( ?. )操作员,上述代码可以替换为

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

    这…有效!为什么?

    3 回复  |  直到 8 年前
        1
  •  20
  •   Joey Gumbo    9 年前

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

        2
  •  14
  •   Tamir Vered    9 年前

    简短回答:

    DateTime? 对于 Nullable<DateTime> 它不包含 DateTime 的属性和方法 Elvis操作符处理不可为Null的 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 级别,并且由于该值稍后不会在反编译器中使用,因此反编译器将其显示为好像它是在内部声明的 如果 范围

    正如你所见 日期时间? 对于 可为空<日期时间> , C# 有特定的参考 Nullable<T> s与 Elvis操作员 ,使其返回值 不可为空的T本身 .

    整体的结果 Elvis operator 必须是 Nullable 因此,如果你想收到非- 一串 值必须是 可为空<T> ReferenceType 但这并不能改变这样一个事实,即如果运营商设法获得 可为空<日期时间> 值本身-返回的 日期时间 不是 可为空<日期时间> 不再

        3
  •  2
  •   Orace    9 年前

    考虑到:

    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 女巫是 I可格式化 并有一个 ToString(字符串格式) 方法

    最后,用C#5.0编写第一段代码的好方法是:

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