Why does the C# compiler translate this != comparison as if it were a > comparison?
Question:
I have by pure chance discovered that the C# compiler turns this method:
static bool IsNotNull(object obj)
{
return obj != null;
}
…into this IL:
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0 // obj
ldnull
cgt.un
ret
}
…or, if you prefer looking at decompiled C# code:
static bool IsNotNull(object obj)
{
return obj > null; // (note: this is not a valid C# expression)
}
How come that the != gets
translated as a ">"?
Answer:
Short answer:
There is no "compare-not-equal" instruction in IL, so the C# != operator
has no exact correspondence and cannot be translated literally.
There is however a "compare-equal" instruction (ceq,
a direct correspondence to the == operator),
so in the general case, x gets translated like its slightly longer equivalent
!= y(x.
== y) == false
There is also a "compare-greater-than" instruction in IL (cgt)
which allows the compiler to take certain shortcuts (i.e. generate shorter IL code), one being that inequality comparisons of objects against null, obj, get translated as if they were "
!= nullobj".
> null
Let's go into some more detail.
If there is no "compare-not-equal" instruction in IL, then how will the following method get translated by the compiler?
static bool IsNotEqual(int x, int y)
{
return x != y;
}
As already said above, the compiler will turn the x into
!= y(x:
== y) == false
.method private hidebysig static bool IsNotEqual(int32 x, int32 y) cil managed
{
ldarg.0 // x
ldarg.1 // y
ceq
ldc.i4.0 // false
ceq // (note: two comparisons in total)
ret
}
It turns out that the compiler does not always produce this fairly long-winded pattern. Let's see what happens when we replace y with
the constant 0:
static bool IsNotZero(int x)
{
return x != 0;
}
The IL produced is somewhat shorter than in the general case:
.method private hidebysig static bool IsNotZero(int32 x) cil managed
{
ldarg.0 // x
ldc.i4.0 // 0
cgt.un // (note: just one comparison)
ret
}
The compiler can take advantage of the fact that signed integers are stored in two's complement(where,
if the resulting bit patterns are interpreted as unsigned integers — that's what the .un means
— 0 has the smallest possible value), so it translates x as if it were
== 0unchecked((uint)x).
> 0
It turns out the compiler can do just the same for inequality checks against null:
static bool IsNotNull(object obj)
{
return obj != null;
}
The compiler produces almost the same IL as for IsNotZero:
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0
ldnull // (note: this is the only difference)
cgt.un
ret
}
Apparently, the compiler is allowed to assume that the bit pattern of the null reference
is the smallest bit pattern possible for any object reference.
This shortcut is explicitly mentioned in the Common Language Infrastructure Annotated Standard
(1st edition from Oct 2003) (on page 491, as a footnote of Table 6-4, "Binary Comparisons or Branch Operations"):
"
cgt.unis
allowed and verifiable on ObjectRefs (O). This is commonly used when comparing an ObjectRef with null (there is no "compare-not-equal" instruction, which would otherwise be a more obvious solution)."
Why does the C# compiler translate this != comparison as if it were a > comparison?的更多相关文章
- deque Comparison of Queue and Deque methods Comparison of Stack and Deque methods
1. 队列queue和双端队列deque的转换 Queue Method Equivalent Deque Methodadd(e) addLast(e)offer(e) offerLast(e)re ...
- .NET (四)委托第四讲:内置委托Comparison
// 摘要: // 表示比较同一类型的两个对象的方法. // // 参数: // x: // 要比较的第一个对象. // // y: // 要比较的第二个对象. // // 类型参数: // T: / ...
- EF 5 最佳实践白皮书
Performance Considerations for Entity Framework 5 By David Obando, Eric Dettinger and others Publish ...
- Intel graphics processing units
http://en.wikipedia.org/wiki/Comparison_of_Intel_graphics_processing_units Comparison of Intel graph ...
- Oracle Database 11g express edition
commands : show sys connect sys as sysdba or connect system as sysdba logout or disc clear screen or ...
- SAP ABAP 处理字符串串串串串串串串(详细)
关于ABAP中处理字符串的方法,非常详细,学习过程中总结一下分享给大家,,, ABAP/4 提供多个处理类型 C 即字符串 的数据对象的关键字. 处理字符串 的方法有: 1.拆分字符串split 2. ...
- RFC 2616
Network Working Group R. Fielding Request for Comments: 2616 UC Irvine Obsoletes: 2068 J. Gettys Cat ...
- 教程less
http://lesscss.cn/features/ Overview As an extension to CSS, Less is not only backwards compatible w ...
- 【转】Everything you need to know about NoSQL databases
原文: https://dev.to/lmolivera/everything-you-need-to-know-about-nosql-databases-3o3h ---------------- ...
随机推荐
- css概括2
Css内容: 常用样式:字体.颜色.背景... 字体:大小.颜色.粗细.字体 Text-decoration:文本修饰{overline 上 Underline 下 Line-throung 中} T ...
- Spring AOP中pointcut expression表达式
Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方式来定义或者通过&am ...
- emr hadoop 参数调优
set hive.merge.mapfiles=true; set hive.merge.mapredfiles=true; ; ; set hive.exec.compress.intermedia ...
- VB.NET 定义多行文本字符的几种方式
vbCrLf 在 .NET 刚刚推出的时候,VB作为一款被微软用来"衬托"C#的语言,在许多细节设计上远不如C#方便. 比如在C#中写一个多行文本,就有各种方式: string s ...
- 使用autogen生成应用程序遇到问题及解决方法
从github上下载的代码,运行autogen.sh的时候,上报错误: $ ./autogen.sh --prefix=/usr./autogen.sh: 10: ./autogen.sh: auto ...
- python中不同文件中函数和类的调用
最近在学习Python的时候,遇到了一个不同文件中类无法调用的问题,搜了很多,发现很多人针对 这个问题都说的相当含糊,让我费了好大劲才把这个东东搞明白.记录一下,权且温习. 调用分两种,一种是同种文件 ...
- Win10手记-取色器ColorPicker的实现
最近个人项目需要用到ColorPicker,但是适用于WinRT和Win10的基本没用,所以只能自己造轮子了. 平台环境 Windows 10 Visual Studio 2015 思路 确定需求后, ...
- Java线程池种类、区别和适用场景
newCachedThreadPool: 底层:返回ThreadPoolExecutor实例,corePoolSize为0:maximumPoolSize为Integer.MAX_VALUE:keep ...
- vscode中iview的</Col>标签报错问题
直接看问题截图: 这是vetur中eslint的问题,在vscode菜单中,文件->首选项->设置 找到 “vetur.validation.template”: true 将其改为fal ...
- Django Rest Swagger生成api文档
关于swagger Swagger能成为最受欢迎的REST APIs文档生成工具之一,有以下几个原因: Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API. Sw ...