sta*_*ica 147 c# il cil binary-operators notnull
我有机会发现C#编译器会改变这个方法:
static bool IsNotNull(object obj)
{
return obj != null;
}
Run Code Online (Sandbox Code Playgroud)
...进入这个CIL:
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0 // obj
ldnull
cgt.un
ret
}
Run Code Online (Sandbox Code Playgroud)
...或者,如果您更喜欢查看反编译的C#代码:
static bool IsNotNull(object obj)
{
return obj > null; // (note: this is not a valid C# expression)
}
Run Code Online (Sandbox Code Playgroud)
怎么把它!=翻译成" >"?
sta*_*ica 201
IL中没有"比较不等于"指令,因此C#!=运算符没有确切的对应关系,也无法按字面翻译.
然而,存在"比较相等"指令(ceq与==操作员的直接对应),因此在一般情况下,x != y被翻译为稍长的等价物(x == y) == false.
有也是一个"比较,大于"在IL(指令cgt),它允许编译采取一定的快捷键(即产生较短的IL代码),一个是对空的对象,不平等的比较,obj != null,得到翻译,好像他们是" obj > null".
如果IL中没有"compare-not-equal"指令,那么编译器将如何翻译以下方法?
static bool IsNotEqual(int x, int y)
{
return x != y;
}
Run Code Online (Sandbox Code Playgroud)
正如上面已经说了,编译器会转x != 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
}
Run Code Online (Sandbox Code Playgroud)
事实证明,编译器并不总是产生这种相当冗长的模式.让我们看看当我们y用常数0 替换时会发生什么:
static bool IsNotZero(int x)
{
return x != 0;
}
Run Code Online (Sandbox Code Playgroud)
产生的IL比一般情况略短:
.method private hidebysig static bool IsNotZero(int32 x) cil managed
{
ldarg.0 // x
ldc.i4.0 // 0
cgt.un // (note: just one comparison)
ret
}
Run Code Online (Sandbox Code Playgroud)
编译器可以利用有符号整数存储在二进制补码中的事实(其中,如果结果位模式被解释为无符号整数 - 这就是.un意味着 - 0具有最小可能值),因此它的翻译x == 0就好像它是unchecked((uint)x) > 0.
事实证明,编译器可以对不等式检查执行相同的操作null:
static bool IsNotNull(object obj)
{
return obj != null;
}
Run Code Online (Sandbox Code Playgroud)
编译器生成的IL与以下几乎相同IsNotZero:
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0
ldnull // (note: this is the only difference)
cgt.un
ret
}
Run Code Online (Sandbox Code Playgroud)
显然,允许编译器假设null引用的位模式是任何对象引用可能的最小位模式.
此快捷方式在公共语言基础结构注释标准(2003年10月第1版)中明确提及(第491页,作为表6-4"二进制比较或分支操作"的脚注):
"
cgt.un在ObjectRefs(O)上允许并验证.这通常在将ObjectRef与null进行比较时使用(没有"compare-not-equal"指令,否则这将是一个更明显的解决方案)."
| 归档时间: |
|
| 查看次数: |
5384 次 |
| 最近记录: |