为什么null==false不会导致c#中的编译错误?

为什么null==false不会导致c#中的编译错误?,c#,compiler-construction,C#,Compiler Construction,这并不是为了解决任何特定的问题。只是一个编译器问题 为什么下面的代码不会导致编译错误?它将引用类型与基元类型进行比较。null和false都必须被解释为编译器要进行比较的内容。或者解析器只是扫描这样的模式并用false替换它 if(null == false) { } 这是合法的,因为使用了提升比较运算符。如果将bool与null进行比较,则bool和null都会隐式转换为Nullable,并且Nullable的比较运算符最终会被使用。您会收到警告,因为很明显,它总是错误的。语言规范第7.10

这并不是为了解决任何特定的问题。只是一个编译器问题

为什么下面的代码不会导致编译错误?它将引用类型与基元类型进行比较。null和false都必须被解释为编译器要进行比较的内容。或者解析器只是扫描这样的模式并用false替换它

if(null == false) { }

这是合法的,因为使用了提升比较运算符。如果将
bool
null
进行比较,则
bool
null
都会隐式转换为
Nullable
,并且
Nullable
的比较运算符最终会被使用。您会收到警告,因为很明显,它总是错误的。

语言规范第7.10.6节(引用类型相等运算符)指出:

即使T可以表示值类型,也允许使用
x==null
构造,并且当T是值类型时,结果仅定义为false


这项规定要求
null==false
be
false
,而不是编译器错误。

Tejas的答案是正确的。要更具体地阐述您的一些观点:

为什么下面的代码不会导致编译错误

这个问题无法回答;它不会产生错误,因为它是法律代码,但这是一个同义反复

如果您的问题实际上是“C#规范的哪一部分使其合法?”,那么这是一个可以回答的问题。关于运算符的部分使其合法

它将引用类型与基元类型进行比较

事实并非如此。首先,避免使用“基本类型”一词;规范没有明确定义它,在C#中它不是一个有用的概念。你的意思是说,我认为这是比较一个引用类型的值和一个值类型的值

第二,这也不正确。空文本不是引用类型或值类型;它不是什么类型的。它可以转换为任何可为null的值类型或任何引用类型,但它本身不是类型

在这种情况下,null文本被转换为可为null的bool类型

null和false都必须被解释为编译器要进行比较的内容

对。它们被解释为可为空的布尔值

解析器只是扫描这样的模式并用false替换它吗

if(null == false) { }

没有,但这是一个很好的猜测。编译器将常数折叠,比如说,
true==false
向下折叠到
false
,但它不执行涉及可空值类型的折叠优化。该语言可以重新设计,以支持对具有可空值类型操作数的操作进行常量折叠;如果可为空的值类型实际出现在版本1中,则建议的功能可能会得到支持。

值类型与否,
false
仍然是一个对象。它可能会被装箱作比较。@cHao:你的猜测是错误的。相等运算符专门设计用于避免装箱;详细阅读说明书。我更喜欢你的答案,因为它解释了为什么允许它以及它是如何工作的。而不是仅仅陈述显而易见的事实。顺便说一句,编译器(在调试模式下关闭优化)甚至不尝试发出它。它只是向代码中发出
false
。根据规范第7.9.10节(相等运算符和null),这是不正确的。此解释仅适用于以下情况:
null==x
x
为可空类型。规范说明这相当于
x.HasValue
。由于文本
false
不是可空类型,因此合法的原因与提升的比较运算符无关。
false
可能不是可空类型,但它属于
bool
类型,并且
bool
bool?
之间存在隐式转换,以下是Eric Lippert关于此主题的帖子这是唯一正确的答案。规范的这一部分仅适用于类型参数。感谢您将记录设置得更清楚。在可为null的类型之前的C#中,比较是否也有效?@AndersForsgren:什么比较有效,在哪个版本的C#中?比较null==false,在C#2引入可空类型之前的C#版本中。也就是说:这是C#1.2中的编译错误吗?我想是找到了。我将规范解释为“是”:7.9.6预定义的引用类型相等运算符不允许比较值类型操作数。