当我调试几行代码并问我原因为什么它无法正常工作时我偶然发现了这种情况......
if(answer.AnswerID == null)
{
// do something
}
实际上它应该是这样的:
if(answer == null)
{
// do something
}
answer
是Answer - a class
类型的对象。AnswerID
是long
类型的属性。奇怪的是,如果你尝试这样的事情:
long myLongValue = null;
编译器会显示错误:
Connot convert null to long ...
所以我的问题是:当我尝试将long type
与null
进行比较时,为什么我没有收到编译错误?
EDITED
此问题不是关于nullable
类型。
我问为什么.NET允许我将长变量与null进行比较。我说的是long type
而不是long? type
。
答案 0 :(得分:31)
正如@Tim指出的那样,您不会收到以下代码的错误:
long foo = 42;
if (foo == null) { }
你会收到警告:
表达式的结果始终为“false”,因为“long”类型的值永远不会等于“long”类型的“null”。
由于lifted operators而在C#语言规范中定义了这样的警告而不是错误:
提升运算符 允许对非可空值类型进行操作的预定义和用户定义运算符也可以与这些类型的可空形式一起使用。 [...]对于相等运算符
== !=
如果操作数类型都是非可空值类型且结果类型为bool,则存在提升形式的运算符。 提升形式是通过添加一个?每个操作数类型的修饰符。提升的运算符认为两个空值相等,并且空值不等于任何非空值。如果两个操作数都是非null,则提升的运算符将解包操作数并应用基础运算符来生成bool结果。
在这种情况下,“基础运营商”是the predefined value type long
's ==
operator:
对于预定义的值类型,如果操作数的值相等,则相等运算符(==)返回true,否则返回false。
因为隐式转换了foo
(“对非可空值类型进行操作的预定义隐式转换也可以与这些类型的可空形式一起使用。”)和{{1文字也被隐式转换(“隐式转换从空文字存在到任何可空类型。”),表达式:
null
变为:
(long)foo == null
考虑到(long?)foo == (long?)null
的类型为foo
,因此总是有值,所以始终返回false,甚至不会应用long
的{{1}}运算符。< / p>
我不完全确定,但我怀疑这是存在的,可以在没有显式转换的情况下对可空值和非可空值进行比较:
long
如果上述指定的语言无法解决此问题,则“操作员==
无法应用于long? foo = 42;
long bar = 42;
Console.WriteLine(foo == bar); // true
foo = null;
Console.WriteLine(bar == foo); // false
和==
类型的操作数”< / em>,因为Nullable<T>
没有long?
运算符,而long
没有==
运算符接受long
。
答案 1 :(得分:8)
它将进行编译,甚至会执行,因为编译器会评估==
并将long
提升为long?
,因为这是与==
实现最接近的匹配存在。
这确实不是最好的行为,它有点像VB: - )
答案 2 :(得分:0)
有关可空类型的信息,请查看here。像long和int这样的普通值类型通常不能为null。
当你试图将它与null进行比较时它没有失败的原因是因为它进行了比较并且它不是null。那里没有错误。