[英]“ulong == ulong?” evaluated as “ulong == ulong” works correctly
如果我们在ulong
表达式和 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;
}
}
ulong?
将值 null 设置为ulong
。 (ulong)(ulong?)null
throws: "Nullable object 必须有一个值。"ulong?
的每个可能值返回正确的值? ,包括null? 如果是这样,怎么做? ulong?
比ulong
多一个可能的值,因此应该有一组两个值 map 到相同的ulong
值,这将引入一个误报“真”结果。 从理论上讲,我可以想象 null 被合并到default(ulong)
,但是上面示例中的结果将是正确的,这将是一个错误的答案。 正如我们所看到的,编译器没有犯这个错误——它回答正确。
来自MSDN :
提升的运算符允许对不可空值类型进行操作的预定义和用户定义运算符也可以与这些类型的可空 forms 一起使用。 提升运算符由满足某些要求的预定义和用户定义的运算符构成,如下所述:
...
对于等式运算符
== !=
如果操作数类型都是不可为空的值类型并且结果类型是
bool
,则存在运算符的提升形式。 提升的形式是通过添加单个?
每个操作数类型的修饰符。 提升的运算符认为两个 null 值相等,并且一个 null 值不等于任何非空值。 如果两个操作数都不为空,则提升的运算符解包操作数并应用底层运算符以产生bool
结果。
您没有使用运算符:
bool ==(ulong left, ulong right)
您正在使用提升的运算符:
bool ==(ulong? left, ulong? right)
这个算子需要两个ulong?
参数,如果两者都是 null,或者两者都为非空且具有相同的值,则返回 true。
您可能正在查看 Visual Studio,它在这种情况下确实向您展示了一些令人困惑的东西:
不要对此感到困惑——正如@mjwills 在评论中指出的那样,这是一个已知问题。
如果你这样写:
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;
}
如果b
是null
,则num.GetValueOrDefault()
返回0
,否则返回b
的值。 因此,当且仅当b
不是 null 并且具有与a
相同的值时, M
返回true
。
如果我们在 ulong 表达式和 ulong? 表达式之间使用 == 运算符,则使用运算符重载 bool ulong(ulong left, ulong right)。
问题的很大一部分是 Visual Studio 的智能感知错误地显示正在使用ulong
的==
运算符(如果您使用 hover 超过==
)。
这是一个错误,根据https://github.com/dotnet/roslyn/issues/21494 。 它实际上并没有使用该运算符。
由于您所有其他问题都是基于该错误前提,因此意识到该错误的存在会使其他问题在很大程度上消失。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.