请考虑以下代码:
DateTime t = DateTime.Today;
bool isGreater = t > null;
使用Visual Studio 2010(C#4,.NET 4.0),我收到以下警告:
警告CS0458:表达式的结果总是'null',类型'bool?'
这是不正确的;结果总是 false
(bool
类型):
现在,struct DateTime重载了>
(大于)运算符。任何不可为空的结构(如DateTime)都可以隐式转换为相应的Nullable<>
类型。上面的表达式完全等同于
bool isGreater = (DateTime?)t > (DateTime?)null;
也会产生相同的错误警告。此处>
运算符是提升运算符。如果其两个操作数中的任何一个HasValue
为false
,则返回false。否则,提升的运算符将继续将两个操作数展开到底层结构,然后调用该结构定义的>
的重载(但在这种情况下,如果一个操作数不是HasValue
则不需要})。
你能重现这个bug,这个bug是众所周知的吗?我误解了什么吗?
所有结构类型(不是像int
这样的简单类型,而不是枚举类型)都是相同的,它会使运算符重载。
(现在,如果我们使用==
而不是>
,那么一切都应该完全相似(因为DateTime也会重载==
运算符)。但它不相似。如果我说< / p>
DateTime t = DateTime.Today;
bool isEqual = t == null;
我得到没有警告☹有时候你会看到人们不小心检查变量或参数为null,没有意识到他们的变量类型是一个结构(重载==
,哪个是不是像int
这样的简单类型。如果他们得到警告会更好。)
更新: 使用Visual Studio 2015的C#6.0编译器(基于Roslyn),更改了上面isGreater
的错误消息进入带有正确且有用的警告消息的CS0464。此外,在VS2015的编译器中修复了上面isEqual
的警告缺失,但仅当您使用/features:strict
进行编译时才会修复。
答案 0 :(得分:5)
你是对的:这是Visual Studio中的一个错误。 C#4.0标准(第7.3.7节解除运营商)有这样的说法:
对于关系运算符
< > <= >=
[...] 如果一个或两个操作数为空,则提升的运算符会生成值
false
。 ...
事实上,在MonoDevelop中,您会收到以下警告:
将
System.DateTime
类型与null
进行比较的结果始终为false
。
答案 1 :(得分:1)
DateTime t = DateTime.Today;
bool isGreater = (DateTime?)t > (DateTime?)null;
在这种情况下,警告的内容是t > null
。这永远不会成真。因为它无法评估。
在这种情况下:
bool isGreater = (DateTime?)t > (DateTime?)null;
我们正在评估(DateTime?)t > (DateTime?)null
;
或者基本上是最好的情况t > null
;和之前一样。 DateTime.Now永远不会大于Undefined,因此警告。