"ulong == ulong?" 评估为 "ulong == ulong" 工作正常

"ulong == ulong?" evaluated as "ulong == ulong" works correctly

如果我们在 ulong 表达式和 ulong? 表达式之间使用 == 运算符,则似乎使用了运算符重载 bool ulong(ulong left, ulong right)

换句话说,运算符认为两个表达式都是非空的。

在此示例程序中,equal 正确地变为 false,无一例外。

void Main()
{
    var temp = new Temp(0);
    object temp2 = null;

    var equal = temp.Id == (temp2 as Temp)?.Id; // False :) but how?
}

public class Temp
{
    public ulong Id {get;}

    public Temp(ulong id)
    {
        this.Id = id;
    }
}
  1. 这怎么能不扔呢?没有从值为 null 的 ulong?ulong 的转换。 (ulong)(ulong?)null 抛出:"Nullable object must have a value."
  2. 这个 return ulong? 的每个可能值 的正确值是否正确,包括 null?如果是这样,如何?类型 ulong?ulong 多一个可能的值,因此应该有一组两个值映射到 same ulong 值,这会引入一个误报 "true" 结果。

理论上,我可以想象 null 被合并为 default(ulong),但是我上面示例中的结果将是真实的,这将是一个错误的答案。正如我们所见,编译器不会犯这个错误 - 它会正确回答。

来自 MSDN:

Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:

...

  • For the equality operators

    ==  !=
    

a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator considers two null values equal, and a null value unequal to any non-null value. If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

您没有使用运算符:

bool ==(ulong left, ulong right)

您正在使用提升运算符:

bool ==(ulong? left, ulong? right)

此运算符采用两个 ulong? 参数,如果两者均为空,或者两者均为非空且具有相同的值,则 returns 为真。


您可能正在查看 Visual Studio,在这种情况下它确实让您感到困惑:

不要对此感到困惑——正如@mjwills 在评论中指出的那样,this is a known issue


如果你这样写:

public bool M(ulong a, ulong? b) {
    return a == b;
}

然后编译器生成以下代码:

public bool M(ulong a, ulong? b)
{
    ulong? num = b;
    return (a == num.GetValueOrDefault()) & num.HasValue;
}

num.GetValueOrDefault() returns 0 如果 bnull,否则值为 b。所以 M returns true 当且仅当 b 不为空,并且与 a.

具有相同的值

SharpLab

If we use the == operator between an expression of ulong and an expression of ulong?, then the operator overload bool ulong(ulong left, ulong right) is used.

问题的很大一部分是 Visual Studio 的智能感知错误地显示正在使用 ulong== 运算符(如果您将鼠标悬停在 == 上)。

根据 https://github.com/dotnet/roslyn/issues/21494,这是一个错误。 实际上 使用该运算符。

由于您所有其他问题都是基于该错误前提,因此意识到该错误的存在会使其他问题基本消失。