c# - 将 struct 与 null 进行比较时出现错误的编译器警告

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

考虑以下代码:

DateTime t = DateTime.Today;

bool isGreater = t > null;

使用 Visual Studio 2010(C# 4、.NET 4.0)时,我收到以下警告:

warning CS0458: The result of the expression is always 'null' of type 'bool?'

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

现在,结构 DateTime 重载了 > (大于)运算符。任何不可为 null 的结构(如 DateTime)都可以隐式转换为相应的 Nullable<>类型。上面的表达式完全等同于

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

这也会产生同样的错误警告。这里是>运算符是提升运算符。这通过在 HasValue 时返回 false 来工作。它的两个操作数中的任何一个都是 false .否则,提升运算符将继续将两个操作数解包到底层结构,然后调用 > 的重载。由该结构定义(但在一个操作数不是 HasValue 的情况下,这不是必需的)。

你能重现这个错误吗?这个错误是众所周知的吗?我是不是误解了什么?

这对于重载相关运算符的所有结构类型(不是像 int 这样的简单类型,也不是枚举类型)都是一样的。

(现在如果我们使用 == 而不是 > ,一切都应该完全相似(因为 DateTime 也会重载 == 运算符)。但它并不相似。如果我说

DateTime t = DateTime.Today;

bool isEqual = t == null;

我收到 no 警告 ☹ 有时你会看到人们不小心检查了一个变量或参数是否为空,没有意识到他们的变量类型是一个结构(它重载了 == 而不是一个简单类型,如 int )。如果他们得到警告会更好。)


更新:使用 Visual Studio 2015 的 C# 6.0 编译器(基于 Roslyn),错误消息 isGreater上面已更改为 CS0464,其中包含正确且有用的警告消息。此外,缺少警告 isEqual以上在 VS2015 的编译器中是固定的,但前提是你用 /features:strict 编译.

最佳答案

我在 Roslyn 中实现提升运算符行为时独立发现了这个错误,并在我离开之前在 Roslyn 中修复了它。

抱歉,您在 10 月份发布时我没有看到它。感谢您将其提交给 Connect!并为错误道歉;这是运算符语义分析中长期存在的错误。

顺便说一句,我将讨论 Roslyn 如何优化 http://ericlippert.com 上的提升表达式本月晚些时候(2012 年 12 月),如果您对这个主题感兴趣,请查看:

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

关于c# - 将 struct 与 null 进行比较时出现错误的编译器警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13046115/

相关文章:

c# - WndProc 处理程序效率低下

c# - FileStream 的 FileMode.OpenOrCreate 覆盖文件

Python比较运算符重载

if-statement - 是什么使安全调用(问号)与经典的解释不同?

c# - 在 C# 中,为什么不能将条件运算符隐式转换为可为 null 的类型

c# - 任务排序的不同方式

c++ - 我可以在 C++ 中通过 > < 比较字符串吗

java - 比较两个对象引用的常见情况

c# - 如何在 C# 中将空值设置为 int?

c# - 创建接收参数的方法的最佳方式