CGI-Guid == null不应该被compi允许

下面描述的行为仅特定于.net-3.5

我只是遇到了C#编译器中最惊人的行为;

我有以下代码:

Guid g1 = Guid.Empty;
bool b1= (g1 == null);

好吧,Guid不能为空,因此它永远不能等于null。我在第2行进行的比较始终返回false。

如果对整数进行相同处理,则编译器会发出警告,指出结果始终为false:

int x=0;
bool b2= (x==null);

我的问题是:为什么编译器允许您将Guid与null进行比较?
据我所知,它已经知道结果总是错误的。
内置转换是否以编译器认为可能为null的方式完成?
我在这里想念什么吗?

Luis Filipe asked 2020-06-26T15:52:33Z
4个解决方案
81 votes

标记是正确的。 定义自己的相等运算符的值类型也自动免费获得定义为可提升的版本。 接受两个可为空的Guid的可为空的相等运算符在这种情况下适用,将被调用,并将始终返回false。

在C#2中,这产生了一个警告,但是由于某种原因,它停止对guid-to-null产生警告,但继续对int-null产生警告。 我不知道为什么; 我还没有时间去调查。

对于错误我深表歉意。 在C#3中重写可为空的逻辑时,我可能弄错了一条警告检测代码路径。向该语言中添加表达式树主要改变了可为空的算术运算的实现顺序。 我在移动该代码时犯了很多错误。 这是一些复杂的代码。

Eric Lippert answered 2020-06-26T15:52:59Z
13 votes

比较是有效的,因为编译器将Guid转换为Nullable<Guid>,然后才有意义。

此处未发出有关警告的错误报告。

请参阅此处,以获得Eric Lippert的完整解释。

Mark Byers answered 2020-06-26T15:53:28Z
1 votes

实际上,有时候Guild == null会返回true。

但是,这很难解释。

在ORM映射框架中(例如,openAccess),当您有一个Guid字段时,其默认值为Guid.Empty,当然有可能出现以下情况:

  • 您添加一个新的Guid字段+一个属性
  • 您升级了旧的数据库模式。在这种情况下,数据库中的所有值都将为NULL。
  • 如果您填充的对象具有为此Guild类型的空列,则该对象当然会获得Guid.Empty值。但是,如果您使用LINQ查询...在LINQ查询中,它看起来Guid尚未填充,因此您需要使用 ==空。 也许这是一个错误,但这就是事实。

简而言之(使用OpenAccess,但可能不仅如此):

var item = GetItems()。Where(i => i.SomeGuidField == null); 会工作,你会得到物品guid为空,这是在架构更新之后。item.First()。SomeGuidField将返回Empty Guid

var item = GetItems()。Where(i => i.SomeGuidField == Guid.Empty); 即使在填充了该项目之后,它将仍然为Guid.Empty并且将返回空结果。

JOKe answered 2020-06-26T15:54:24Z
0 votes

当然,这不仅是csc.exe的问题,对于任何不是C#的csc.exe类型,如果struct以通常的方式重载operator ==,也会看到相同的行为。 框架中的其他示例包括DateTimeTimeSpan

这值得一个编译时警告,因为尽管由于操作员的提升而在技术上是合法的,但由于它总是给出csc.exe,因此这不是有用的比较。因此,这表明程序员有错误。

正如Eric Lippert在回答中所说的那样,Visual C#2.0编译器中存在编译时警告。 在版本3.0到5.0中,警告被意外省略(对于这些“用户定义的” csc.exe类型,但对于诸如csc.exe这样的预定义值类型,而不是对于枚举类型)。

从C#6.0(基于Roslyn)开始,编译器再次检测到此代码问题。 但是,由于向后兼容(?!),除非使用所谓的严格功能编译代码,否则不会发出警告。

要在使用csc.exe文件(最常见的情况)时启用严格,请从Visual Studio卸载项目,编辑文件,并插入XML元素:

<Features>strict</Features>

放入csc.exe文件的每个csc.exe(通常会有多个)。 然后,您会收到警告(如果您使用“将警告视为错误”,则可能会“升级为”错误)。

如果您无法编辑csc.exe,并且从命令行编译时调用csc.exe,请使用以下开关:

/p:Features=strict

csc.exe

如果您不直接使用csc.exe(C#编译器)进行编译,则不使用csc.exe文件,请使用开关:

/features:strict

到命令行上的csc.exe

Jeppe Stig Nielsen answered 2020-06-26T15:55:25Z
translate from https://stackoverflow.com:/questions/2177850/guid-null-should-not-be-allowed-by-the-compiler