Int32
struct没有为==
运算符定义运算符重载方法,所以为什么代码不会导致编译时错误:
if(1 == null) ... ;
答案 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
。所以它不需要运营商。
答案 2 :(得分:3)
原始类型的运算符(除了decimal
之外的每个数字类型)都是由语言定义的,而不是运行时。
他们编译为IL指令而不是方法调用(ceq
)的==
答案 3 :(得分:2)
看看MSDN blog。这包含您问题的答案。