如果(1 == null)不应该导致错误?

时间:2011-05-06 18:57:23

标签: c#

Int32 struct没有为==运算符定义运算符重载方法,所以为什么代码不会导致编译时错误:

if(1 == null) ... ;

4 个答案:

答案 0 :(得分:26)

我们在这里退后一步。这个问题令人困惑,到目前为止,答案并不清楚这里发生了什么。

  

if(1 == null)不应该导致错误吗?

没有。这是合法的,虽然愚蠢。

编译器如何处理像“==”这样的运算符?它通过应用重载分辨率算法来实现。

我们必须确定的第一件事是这是“用户定义的”相等运算符还是“内置”相等运算符。左侧是内置类型。右侧根本没有类型。这些都不是用户定义的类型。因此,不会考虑用户定义的运算符。只考虑内置运营商。

一旦我们知道,问题是“将考虑哪些内置运营商?”内置运算符在规范的第7.10节中描述。它们是int,uint,long,ulong,decimal,float,double,任何枚举类型,bool,char,object,string和任何委托类型的相等运算符。

值类型上的所有相等运算符也具有“提升”形式,该形式采用可为空的值类型。

我们现在必须确定哪些运营商适用。要适用,必须从双方隐式转换为运营商的类型。

没有从int到任何枚举类型,bool,字符串或任何委托类型的隐式转换,所以这些都会从考虑中消失。

(没有从int到uint,ulong等的隐式转换,但由于这是一个文字的转换,因此存在从1到uint,ulong等的隐式转换。)

没有从null到任何非可空值类型的隐式转换,所以这些都会消失。

那会留下什么?这使运算符留在object,int?,long?,uint?,ulong?,double?,float ?, decimal?和char?剩下的可空类型。

我们现在必须确定哪些剩余的适用候选人是唯一的“最佳”运营商。如果运算符类型更具体,则运算符优于另一运算符。 “对象”是最不具体的类型,因此被删除。显然,每个可以为null的int都可以转换为可以为null的long,但并不是每个可空的long都可以转换为nullable int,因此可空的long比nullable int更不具体。所以它被淘汰了。我们继续以这种方式消除运营商。 (在无符号类型的情况下,我们应用一个特殊规则,如果int?和uint?都是选项,那么int?wins。)

我会告诉你细节;最终,该进程将nullable int作为唯一的最佳操作数类型。

因此,您的程序被解释为if((int?)1 == (int?)null),这显然是合法的,并且始终是错误的。

  

Int32 struct没有为==运算符

定义运算符重载方法

你是对的。这与任何事情有什么关系?没有它,编译器完全能够进行分析。我不明白你认为这个事实对你的问题的关系。事实是关于可以在类型上定义的方法,问题是关于重载分辨率如何选择提升的内置运算符。这两件事没有关系,因为“int”不是用户定义的类型。

答案 1 :(得分:4)

这是value type而不是reference type。所以它不需要运营商。

http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

答案 2 :(得分:3)

原始类型的运算符(除了decimal之外的每个数字类型)都是由语言定义的,而不是运行时。

他们编译为IL指令而不是方法调用(ceq)的==

答案 3 :(得分:2)

看看MSDN blog。这包含您问题的答案。