将struct与null进行比较时,编译器警告错误

时间:2012-10-24 09:10:27

标签: c# comparison nullable compiler-warnings lifted-operators

请考虑以下代码:

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;

也会产生相同的错误警告。此处>运算符是提升运算符。如果其两个操作数中的任何一个HasValuefalse,则返回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进行编译时才会修复。

2 个答案:

答案 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,因此警告。