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
!= y
 gets translated like its slightly longer equivalent (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
!= null
, get translated as if they were "obj
> 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
!= y
 into (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
== 0
 as if it were unchecked((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.un is
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?的更多相关文章

  1. 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 ...

  2. .NET (四)委托第四讲:内置委托Comparison

    // 摘要: // 表示比较同一类型的两个对象的方法. // // 参数: // x: // 要比较的第一个对象. // // y: // 要比较的第二个对象. // // 类型参数: // T: / ...

  3. EF 5 最佳实践白皮书

    Performance Considerations for Entity Framework 5 By David Obando, Eric Dettinger and others Publish ...

  4. Intel graphics processing units

    http://en.wikipedia.org/wiki/Comparison_of_Intel_graphics_processing_units Comparison of Intel graph ...

  5. Oracle Database 11g express edition

    commands : show sys connect sys as sysdba or connect system as sysdba logout or disc clear screen or ...

  6. SAP ABAP 处理字符串串串串串串串串(详细)

    关于ABAP中处理字符串的方法,非常详细,学习过程中总结一下分享给大家,,, ABAP/4 提供多个处理类型 C 即字符串 的数据对象的关键字. 处理字符串 的方法有: 1.拆分字符串split 2. ...

  7. RFC 2616

    Network Working Group R. Fielding Request for Comments: 2616 UC Irvine Obsoletes: 2068 J. Gettys Cat ...

  8. 教程less

    http://lesscss.cn/features/ Overview As an extension to CSS, Less is not only backwards compatible w ...

  9. 【转】Everything you need to know about NoSQL databases

    原文: https://dev.to/lmolivera/everything-you-need-to-know-about-nosql-databases-3o3h ---------------- ...

随机推荐

  1. 嵌入式ROM核的调用

    本次设计的工具和源码在:http://download.csdn.net/detail/noticeable/9914766 课程目的:调用quartus II提供的rom(read only mem ...

  2. 瞎搞poj1008

    http://poj.org/problem?id=1008 题意: 两种历法: 1.Haab,一年365天,共19个月,前18月有20天(编号为0-19),最后一个月有5天(编号为0-4)pop(1 ...

  3. ReactNative学习笔记(五)踩坑总结

    已经发现的bug或者问题 Android不支持shadow属性: Animated.Image的borderRadius不生效: setNativeProps无法修改图片的source: 没有直接设置 ...

  4. Thinking in Java from Chapter 10

    From Thinking in Java 4th Edition 内部类 public class Parcel1 { class Contents { private int i = 11; pu ...

  5. linux(centos7)安装docker

    1.检查内核版本,必须是3.10及以上 uname ‐r 2.安装docker yum install docker 3.输入y确认安装 4.启动docker [root@localhost ~]# ...

  6. Git 常用命令备份

    继上次保存了git 多个key共存配置(https://www.cnblogs.com/xiaochangwei/p/9155195.html)后,今天把常见的git命令备份下(最近我的云笔记账号经常 ...

  7. [P2402] 奶牛隐藏

    二分答案+最大流. 对答案建图,若长度≤答案,连边即可.(先要预处理点对间的最短路) 当然得拆点,(否则,就此题而言,就会出现流量x-y不走x-y的最短路边的情况,而是走了一条路径 ,答案约束的仅仅是 ...

  8. 关于小窗滑动,父级body也跟随滑动的解决方案(2)

    当第一次写这个问题的时候,并不知道竟然还会写2,而且(1)也并没有解决问题. 也发现,这个问题,真实也困住了很多人,找到了张鑫旭(http://www.zhangxinxu.com/wordpress ...

  9. 第三章 服务治理:Spring Cloud Eureka

    Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.Spri ...

  10. DPI 计算及速查表

    [来源]ExMobi 二次开发手册 手机屏幕根据密度范围分为五种:低.中.高.超高.超超高,为了确保界面元素在不同的屏幕都能合适的展示,在设计界面元素的 UI 时,UI 工程师建议统一采用 dpi ( ...