【发布时间】:2012-10-14 07:26:34
【问题描述】:
考虑以下代码:
DateTime t = DateTime.Today;
bool isGreater = t > null;
使用 Visual Studio 2010(C# 4、.NET 4.0),我收到以下警告:
警告 CS0458:表达式的结果始终为 'bool?' 类型的 'null'
这是不正确的;结果总是 false(bool 类型):
现在,结构 DateTime 重载了 >(大于)运算符。任何不可为空的结构(如 DateTime)都可以隐式转换为相应的 Nullable<> 类型。上面的表达式完全等价于
bool isGreater = (DateTime?)t > (DateTime?)null;
这也会产生同样的错误警告。这里的> 运算符是lifted 运算符。如果其两个操作数中的任何一个的HasValue 是false,则此方法通过返回false 来工作。否则,提升的运算符将继续将两个操作数解包到底层结构,然后调用该结构定义的> 的重载(但在一个操作数没有HasValue 的情况下,这不是必需的)。
你能重现这个错误吗?这个错误是众所周知的吗?我是不是误会了什么?
这对于所有重载相关运算符的结构类型(不是像int 这样的简单类型,也不是枚举类型)都是相同的。
(现在如果我们使用== 而不是>,一切都应该完全相似(因为DateTime 也重载了== 运算符)。但它并不相似。如果我说
DateTime t = DateTime.Today;
bool isEqual = t == null;
我收到 no 警告 ☹ 有时您会看到人们不小心检查了一个变量或参数是否为 null,而没有意识到他们的变量的类型是一个结构(重载 == 而不是像int这样的简单类型。如果他们得到警告会更好。)
更新: 使用 Visual Studio 2015 的 C# 6.0 编译器(基于 Roslyn),上面带有 isGreater 的错误消息更改为带有正确且有用的警告信息。此外,上面isEqual 缺少警告已在VS2015 的编译器中修复,但前提是您使用/features:strict 进行编译。
【问题讨论】:
-
[anything] > null一开始没有任何意义(至少对我而言)。尽管如此,有趣的问题,我认为它应该警告bool总是以false结尾。 -
有趣的是,
DateTime.CompareTo(object)特别是在与null进行比较时返回1,无论传入的对象类型如何。 -
同样的警告出现在 VS 2012 with .net 4.5 :)
标签: c# comparison nullable compiler-warnings lifted-operators