【问题标题】:Non-nullable DateTime (in)equality with null compiles and runs?不可为空的日期时间(不)相等与空编译和运行?
【发布时间】:2019-09-30 07:54:14
【问题描述】:

基于this question,当这段代码编译并运行时,我(以及上述问题中的 OP)感到困惑:

DateTime dateTime = new DateTime();
bool isFalse = dateTime == null;
bool isTrue  = dateTime != null;

注意dateTime 变量不是nullable。当我将鼠标悬停在等号上时,它告诉我它的签名是 bool DateTime.operator==(DateTime dateTime1, DateTime dateTime2)nullNullable<DateTime>

编译器在这里做什么?是否使用某种隐式转换?

我发现了类似的问题here,但它只是对问题不以为然,并没有解释编译器为什么这样做。

【问题讨论】:

    标签: .net datetime compilation


    【解决方案1】:

    根据Binary operator overload resolution的规则:

    x op y 形式的运算,其中 op 是可重载的二元运算符,xX 类型的表达式,yY 类型的表达式,被处理为如下:

    • 确定XY为操作operator op(x,y)提供的候选用户定义运算符集。该集合由X 提供的候选运算符和Y 提供的候选运算符的联合组成,每个运算符都使用候选用户定义运算符的规则确定。 [...]

    Candidate user-defined operators 说:

    对于T0 中的所有operator op 声明以及此类运算符的所有提升形式,如果至少一个运算符适用于参数列表A,则候选集运算符由T0 中的所有此类适用运算符组成。

    Lifted operators:

    提升运算符允许对不可为空的值类型进行操作的预定义和用户定义的运算符也可以与这些类型的可空形式一起使用。提升运算符由满足特定要求的预定义和用户定义的运算符构成,如下所述:

    [...]

    • 对于相等运算符== != 如果操作数类型都是不可为空的值类型并且结果类型是bool,则存在运算符的提升形式。提升形式是通过向每个操作数类型添加单个 ? 修饰符来构造的。提升的运算符认为两个空值相等,一个空值不等于任何非空值。如果两个操作数都不为 null,则提升的运算符会解开操作数并应用底层运算符以生成 bool 结果。

    因此编译器查看操作数DateTimenull,找到用户定义的==(DateTime, DateTime) operator,并将其提升到==(DateTime?, DateTime?)。由于DateTimenull 都可以隐式转换为DateTime?,所以这个提升的运算符是适用的,并最终被选为最佳候选。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2011-05-10
      • 2015-11-02
      相关资源
      最近更新 更多