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 ---------------- ...
随机推荐
- js-function作用域
你能猜出先弹出什么吗? <!DOCTYPE html> <html lang="en"><head> <meta charset=&quo ...
- Android-Java-抽象类
定义抽象类,就一定会定义抽象方法,抽象方法没有方法体{},就证明抽象方法 是不运行的,抽象方法 是给子类继承覆盖运行的, 子类继承->抽象类 就必须覆盖抽象方法,否则编译都失败: 水果案例: 定 ...
- 如何读取R 的sumary()结果
思路 step 1: sum = summary(model) step 2: sum有好多属性,直接根据属性名称引用($)即可, 如: + > sum$call 返回 model 使用的模型语 ...
- MySQL学习笔记1(增删查改)
创建表: /* 创建数据库 create database 数据库名; */ CREATE DATABASE mybase; /* 使用数据库 use 数据库名 */ USE mybase; /* 创 ...
- Java学习笔记36(File类)
File类可以对操作系统中的文件进行操作: File类的静态成员变量: package demo; import java.io.File; public class FileDemo { publi ...
- Spring boot MultipartResolver
[参考文章]:Required MultipartFile parameter 'file' is not present [参考文章]:Springboot2.0中WebMvcConfigurerA ...
- python(32)——【shelve模块】【xml模块】
一. shelve模块 json和pickle模块的序列化和反序列化处理,他们有一个不足是在python 3中不能多次dump和load,shelve模块则可以规避这个问题. shelve模块是一个简 ...
- 【LeetCode】7. 整数反转
题目 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1:输入: 123 输出: 321 示例 2:输入: -123 输出: -321 示例 3:输入: 120 输出 ...
- Django--视图函数views
1 视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. ...
- django model数据 时间格式
from datetime import datetime dt = datetime.now() print '时间:(%Y-%m-%d %H:%M:%S %f): ' , dt.strftime( ...