如果我们在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?到ulong的转换。(ulong)(ulong?)null抛出:“可空对象必须有一个值。”ulong?值(包括null )返回正确的值?如果是这样的话,是怎么做的?类型ulong?比ulong具有更多的可能值,因此应该有一组映射到相同ulong值的值,这将引入一个假阳性的"true“结果。理论上,我可以想象null合并到default(ulong)中,但是上面的例子中的结果将是正确的,这将是一个不正确的答案。正如我们所看到的,编译器没有犯这个错误--它的答案是正确的。
发布于 2019-10-15 12:09:01
来自MSDN
解除运算符允许对非空值类型操作的预定义运算符和用户定义运算符也与这些类型的可空形式一起使用。提升操作符是由符合某些要求的预定义和用户定义的操作符构造的,如下所述: ..。
如果操作数类型都是非空值类型,如果结果类型是bool,则存在操作符的提升形式。提升表单是通过向每个操作数类型添加一个?修饰符来构造的。提升运算符认为两个空值相等,一个空值等于任何非空值.如果两个操作数都为非空,则解除运算符将对操作数展开包装,并应用基础运算符来生成bool结果。
你不用接线员:
bool ==(ulong left, ulong right)您使用的是解除操作符:
bool ==(ulong? left, ulong? right)这个操作符接受两个ulong?参数,如果两者都是空的,或者如果两者都是非空的,并且具有相同的值,则返回true。
您可能会看到Visual,在本例中,它确实给您展示了一些令人困惑的东西:

不要对此感到困惑--正如@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;
}如果num.GetValueOrDefault()是null,则返回0,否则返回b的值。因此,M返回true当且仅当b不是null,并且具有与a相同的值。
发布于 2019-10-15 12:14:34
如果在ulong表达式和ulong表达式之间使用==运算符,则使用运算符重载bool (ulong左侧,ulong右侧)。
问题的很大一部分是Visual的intellisense错误地显示了正在使用的ulong的==操作符(如果您悬停在==上)。
按照https://github.com/dotnet/roslyn/issues/21494的说法,这是一个bug。它实际上并没有使用那个操作符。
因为你所有的其他问题都是基于这个错误的前提,认识到这个错误的存在使得其他问题基本上消失了。
https://stackoverflow.com/questions/58394185
复制相似问题