比较结构时,空错误编译器警告(Wrong compiler warning when compari

2019-07-02 11:04发布

考虑下面的代码:

DateTime t = DateTime.Today;

bool isGreater = t > null;

在Visual Studio 2010中(C#4,.NET 4.0),我得到以下警告:

警告CS0458:表达式的结果总是类型的'空'布尔?

这是不正确; 结果总是false (类型bool ):

现在,该结构的DateTime重载> (大于)运算符。 任何非可空结构(如日期时间)是隐式转换为相应的Nullable<>类型。 上述表达式是完全等同于

bool isGreater = (DateTime?)t > (DateTime?)null;

这也产生了同样的错误的警告。 这里>运营商提升运算。 这是通过返回false如果HasValue的任何两个操作数是false 。 否则,该提升运算符将继续到两个操作数解开到底层结构,然后调用的过载>由该结构定义(但这不是必要在这种情况下,其中一个操作数不HasValue )。

你可以重现这个bug,并且这个bug知名? 我有没有误解的东西吗?

这是所有结构类型(不是简单的类型,如在同一int其超载运营商的问题,而不是枚举类型)。

(现在,如果我们使用==代替> ,一切都应该是完全相似(因为日期时间也重载==操作符),但它不是相似的。如果我说

DateTime t = DateTime.Today;

bool isEqual = t == null;

没有得到任何警告☹有时候你看到人们意外地检查变量或参数为空,却没有意识到他们的变量的类型是一个结构(其中超载==而这不是一个简单的类型一样int )。 它会更好,如果他们得到了一个警告。)


更新:随着C#6.0编译器(基于罗斯林的Visual Studio 2015年),与不正确的消息isGreater上述变更为CS0464具有正确的和有益的警告消息。 此外,缺乏与警告isEqual上述固定在VS2015的编译器,但前提是你有编译/features:strict

Answer 1:

你是正确的: 这是在Visual Studio中的错误 。 在C#4.0标准(第7.3.7抬升运营商)有这样一段话:

对于关系运算符

 < > <= >= 

[...] 的提升运算的结果为false ,如果一个或两个操作数都为空。 ...

而事实上,在MonoDevelop中,你会得到如下的警告,而不是:

类型比较的结果System.DateTimenull永远是false



Answer 2:

我发现独立而在罗斯林执行提升运算符的行为这个错误,我固定它罗斯林在我离开之前。

对不起,我没有看到这个当你张贴早在十月。 感谢您提交它连接! 而很多道歉的错误; 它是在操作语义分析一个长期存在的错误。

顺便说一句,我将讨论罗斯林优化了怎么解除了对表达式http://ericlippert.com本月底(2012年12月),因此,如果这个问题你感兴趣,看看:

http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/



Answer 3:

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不能超过不定,因此警告更大。



文章来源: Wrong compiler warning when comparing struct to null