3 回答
TA贡献1790条经验 获得超9个赞
显然,JIT编译器可以为第一种情况生成的机器代码更加高效。一个真正有用的规则是,只能将对象取消装箱到与盒装值具有相同类型的变量。这允许JIT编译器生成非常有效的代码,不必考虑任何值转换。
的就是运营商的测试很容易,只要检查对象是不是null,而是预期的类型的,但需要一些机器代码指令。转换也很简单,JIT编译器知道对象中值位的位置并直接使用它们。没有复制或转换,所有机器代码都是内联的,只需要十几条指令。当拳击很常见时,这需要在.NET 1.0中真正有效。
转为int?需要做更多的工作。盒装整数的值表示与内存布局不兼容Nullable<int>
。由于可能的盒装枚举类型,需要进行转换并且代码很棘手。JIT编译器生成对名为JIT_Unbox_Nullable的CLR帮助函数的调用,以完成工作。这是任何值类型的通用函数,有很多代码用于检查类型。并且值被复制。由于此代码被锁定在mscorwks.dll中,因此很难估算成本,但很可能有数百条机器代码指令。
Linq OfType()扩展方法也使用了is运算符和强制转换。然而,这是对通用类型的强制转换。JIT编译器生成对辅助函数JIT_Unbox()的调用,该函数可以执行强制转换为任意值类型。我没有一个很好的解释,为什么它与演员一样慢Nullable<int>
,因为应该做的工作少。我怀疑ngen.exe可能会在这里造成麻烦。
TA贡献1744条经验 获得超4个赞
这是上面的FindSumWithAsAndHas的结果:
这是FindSumWithCast的结果:
发现:
使用时
as
,首先测试一个对象是否是Int32的一个实例; 它正在使用isinst Int32
(它类似于手写代码:if(o是int))。并且使用时as
,它也无条件地拆除对象。而且它是一个真正的性能杀手来称呼一个属性(它仍然是引擎盖下的一个功能),IL_0027使用强制转换,首先测试对象是否为
int
if (o is int)
; 在引擎盖下这是使用isinst Int32
。如果它是int的实例,那么您可以安全地取消装入值IL_002D
简单地说,这是使用as
方法的伪代码:
int? x;(x.HasValue, x.Value) = (o isinst Int32, o unbox Int32)if (x.HasValue) sum += x.Value;
这是使用强制转换方法的伪代码:
if (o isinst Int32) sum += (o unbox Int32)
所以演员表((int)a[i]
好吧,语法看起来像一个演员,但实际上是拆箱,演员和拆箱共享相同的语法,下次我会用正确的术语迂腐)方法真的更快,你只需要取消装箱值当一个物体明确地是一个int
。使用as
方法不能说同样的事情。
- 3 回答
- 0 关注
- 414 浏览
添加回答
举报