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. 8. Filters in ASP.NET MVC 5.0【ASP.NET MVC 5.0中的过滤器】

    ASP.NET Filers用来在MVC框架的不同请求处理阶段,注入额外的逻辑.过滤器为横切关注点提供了一种方法(日志记录,授权,缓存). 在这篇文章中,我将会向你介绍MVC框架支持的各种不同种类过滤 ...

  2. Android 和 iOS 实现录屏推流的方案整理

    一.录屏推流实现的步骤 1. 采集数据 主要是采集屏幕获得视频数据,采集麦克风获得音频数据,如果可以实现的话,我们还可以采集一些应用内置的音频数据. 2. 数据格式转换 主要是将获取到的视频和音频转换 ...

  3. kubernetes集群搭建(4):node节点安装

    下列所有操作需要在所有node节点上操作,并注意红色部分的修改 1.node节点不需要安装etcd来存储相关信息 yum -y install flannel kubernetes 2.修改flann ...

  4. 干货—MySQL常见的面试题+索引原理分析!

    目录 MySQL索引的本质 MySQL索引的底层原理 MySQL索引的实战经验 面试 问:数据库中最常见的慢查询优化方式是什么? 同学A:加索引. 问:为什么加索引能优化慢查询? 同学A:...不知道 ...

  5. 机器学习技法笔记:09 Decision Tree

    Roadmap Decision Tree Hypothesis Decision Tree Algorithm Decision Tree Heuristics in C&RT Decisi ...

  6. python tricks

    1. cities = ['Marseille', 'Amsterdam', 'New York', 'Londom'] # the good way for i, city in enumerate ...

  7. iOS-SVProgressHUDMaskType

    SVProgressHUDMaskTypeNone:默认图层样式,当HUD显示的时候,允许用户交互.   SVProgressHUDMaskTypeClear:当HUD显示的时候,不允许用户交互.   ...

  8. 使用Masonry对UIScrollView自动布局

    之前使用Masonry对UIScrollView进行过约束,当时是遇到了问题的,怎么约束都不对,因为赶进度直接改用frame了也没有对问题深究.就这样过了很久.........,直到前一段换工作的时候 ...

  9. C# Winform同时启动多个窗体类

    首先创建一个类,存放将要同时显示的窗体 using System; using System.Collections.Generic; using System.Linq; using System. ...

  10. Postgresql ---plv8扩展(windows下安装过程)

    Postgresql下plv8安装过程其实很简单,但是在网络上搜集了半天都没有找到一篇满意的安装文档,现在总结如下: 1.下载和PostgreSQL相对应的plv8版本,下载地址如下: http:// ...