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 ---------------- ...
随机推荐
- Go语言正则模块
基本使用 import "bytes" import "fmt" import "regexp" func main() { //这个测试一 ...
- 分享《机器学习实战基于Scikit-Learn和TensorFlow》中英文PDF源代码+《深度学习之TensorFlow入门原理与进阶实战》PDF+源代码
下载:https://pan.baidu.com/s/1qKaDd9PSUUGbBQNB3tkDzw <机器学习实战:基于Scikit-Learn和TensorFlow>高清中文版PDF+ ...
- CentOS操作系统防火墙添加例外端口
http://blog.csdn.net/inrgihc/article/details/63392004 CentOS6与CentOS7添加防火墙例外端口的命令不用,需单独来说: (1)CentOS ...
- Shiro 基础教程
原文地址:Shiro 基础教程 博客地址:http://www.extlight.com 一.前言 Apache Shiro 是 Java 的一个安全框架.功能强大,使用简单的Java安全框架,它为开 ...
- Baidu WebUploader 前端文件上传组件的使用
简介 WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流I ...
- Java学习笔记47(JDBC、SQL注入攻击原理以及解决)
JDBC:java的数据库连接 JDBC本质是一套API,由开发公司定义的类和接口 这里使用mysql驱动,是一套类库,实现了接口 驱动程序类库,实现接口重写方法,由驱动程序操作数据库 JDBC操作步 ...
- 【书籍推荐】java初级到中级书籍推荐
<编码>--必读 <程序是怎么跑起来的> --必读 <计算机系统概论> <深入理解计算机>--部分章节必读 <操作系统概论> <计算机 ...
- python实现线性排序算法-计数排序
计数排序假定输入元素的每一个都是介于0到k之间的整数,此处K为某个整数,当k=O(n)时,计数排序的运行时间为O(n) 它的基本思想是:根据每个输入元素x确定小于x的元素个数,根据这个信息把x直接放到 ...
- Linux - 常用网络操作
001 - Linux CentOS网络配置 CentOS---网络配置详解 002 - Linux查看端口状态 检测本机8080端口状态:netstat –apn | grep 8080 检测192 ...
- rest framework 尝鲜
安装 pip install djangorestframework 新建项目 python manage.py startapp idcs 添加模型(models.py) class Idcs(mo ...