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 ---------------- ...
随机推荐
- B - Dropping tests
In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cum ...
- Jmeter 结构、原理介绍 Jmeter结构、原理介绍(1)
一.Jmeter 简介 1.是基于java语言的开源的应用软件. 2.可以进行接口测试.性能测试.接口及性能的自动化测试. 二.Jmeter体系结构 元件:可以理解为每一个菜单.如THHP请求.响应断 ...
- 菜鸟在ubuntu 16.04下制作am335x的SD卡启动盘反思
以前只在消费电子平台android和rtos上做软件,每次都是公司的环境现成的,根本不用去想启动加载那部分 的事情,最近在做一个工控机的项目时,接触到了TI的arm335x系列的平台,才发现在嵌入式的 ...
- LeetCode--No.003 Longest Substring Without Repeating Characters
Longest Substring Without Repeating Characters Total Accepted: 167158 Total Submissions: 735821 Diff ...
- 3-5 Vue中的样式绑定
Vue中的样式绑定: 本案例,简单设计一个<div>的点击绑定事件来改变div的样式效果 方法一:[class] ①(class和对象的绑定) //如上,运用class和一个对象的形式来解 ...
- vue父子组件传递参数之props
vue中父组件通过props传递数据给子组件, props有两种传递方式 1.props:['msg']2.props: { msg:{ type:String, default:"&quo ...
- Android中内容提供者ContentProvider的详解
1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...
- salesforce零基础学习(八十八)项目中的零碎知识点小总结(二)
通过做项目以及群里面的一些大神的聊天,总结一下关于项目中的两个知识点,以后当做参考. 一. 在custom setting中配置集成接口信息后刷sandbox的问题 我们做项目时,经常会遇见和其他平台 ...
- java对文件的检索
先说下思路吧. 1.先把xls等文件转换为静态html文件:可以用很多插件,类似我的博客地址: http://www.cnblogs.com/Alandre/p/3221006.html 2.再对转的 ...
- Eureka单机高可用伪集群配置
Eureka Server高可用集群理论上来讲,因为服务消费者本地缓存了服务提供者的地址,即使Eureka Server宕机,也不会影响服务之间的调用,但是一旦新服务上线,已经缓存在本地的服务提供者不 ...