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. SimpleCursorAdapter和ListView的结合使用

    我们在用SQLite查数据的时候,经常会用到Cursor这个游标,我们希望能将游标指向的数据直接绑定到ListView中,这样就免去了将游标数据取出然后转换到SimpleAdapter中的麻烦.今天我 ...

  2. CentOS 7安装新版RabbitMQ解决Erlang 19.3版本依赖

    通过yum等软件仓库都可以直接安装RabbitMQ,但版本一般都较为保守. RabbitMQ官网提供了新版的rpm包(http://www.rabbitmq.com/download.html),但是 ...

  3. 另一个画风的GSS1 - Can you answer these queries I(猫树)

    前言 其实我觉得你看猫锟的解释也看不懂(主要是还有一些不良心的讲解者不讲清楚,当然这里不是针对了qwq) 猫锟链接 Solution 考虑我们的线段树是个啥玩意? 每一层都是一堆区间叠在一起. 我们在 ...

  4. Varnish实现Web站点加速

    Varnish 是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang使用3台Varnish代替了原来的12台Squid,性能比以前更好. Varnish 的作者Poul-He ...

  5. 2017CS231n学习笔记——计算机视觉的概述

    本节课主要讲述了cs231n课程的背景和计算机视觉的历史,也主要介绍了目前很重要的一个计算机视觉数据集--IMAGENET. 更多内容参考我的AI学习之路 课程简介 这门课程是由stanford大学计 ...

  6. Java中List, Integer[], int[]的相互转换

    import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Mai ...

  7. JavaScript中的constructor和继承

    概述 这是我在看JavaScript面向对象编程指南的时候,对constructor和继承的总结. 关于它们的详细知识,可以上网查到,所以我只写那些网上没有的. 内容 constructor的理解 c ...

  8. 一个linux内核编译时遇到的perl语法导致的编译问题解决

    在编译linux内核时,遇到了一个比较诡异的问题.具体log如下: Can't locate strict.pm in @INC (you may need to install the strict ...

  9. 了解甚少的GNU C的__attribute__ 机制

    平时忙着赶项目,很多东西都是不求甚解,当工作中遇到的一些比较刁钻的问题时,才发现自己和那些大牛的 差距---内功.熟练码农和码神的最大区别估计就是内功是否深厚了.在自我反思的过程中,也要逐渐的积累一些 ...

  10. Go 新起点

    因项目需求 又得开始啃Go了,虽然比计划早了点,撸起袖子开始干吧~