当前位置 : 主页 > 网络安全 > 测试自动化 >

.NET 4.0 Dictionary:值类型键,用于无效的’null’检查.这会伤害性能吗?

来源:互联网 收集:自由互联 发布时间:2021-06-22
例如: .method private hidebysig instance void Insert(!TKey key, !TValue 'value', bool add) cil managed{ .maxstack 3 .locals init ( [0] int32 num, [1] int32 num2, [2] int32 num3, [3] int32 num4) L_0000: ldarg.1 L_0001: box !TKey L_0006:
例如:

.method private hidebysig instance void Insert(!TKey key, !TValue 'value', bool add) cil managed
{
    .maxstack 3
    .locals init (
        [0] int32 num,
        [1] int32 num2,
        [2] int32 num3,
        [3] int32 num4)
    L_0000: ldarg.1 
    L_0001: box !TKey
    L_0006: brtrue.s L_000e
    L_0008: ldc.i4.5 
    L_0009: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)

这是来自Dictionary< int,Object>的内部Add方法.在.NET 4.0中.尽管泛型被广泛吹捧为有助于避免值类型的装箱,但为什么这个系统组件对值类型键的每个操作都进行了低效的检查?如果我理解正确,这不仅会伤害性能,而且总会返回true(盒装值类型永远不会是空引用)

编辑:Marc对这个特定问题的答案摘要:重要的原因是这个词典< K,V>实现选择不允许使用“null”Nullable< T>实例作为键.因为MSIL盒指令对Nullable< T>给出特殊处理.值类型,对于所有值类型,检查不一定是徒劳的.

Nullable< T>是一个struct / value-type,可以为null(取决于你对null的定义;但肯定它可以为null).并非所有TKey都是值类型(字符串可能是最常见的TKey).

这里要求密钥不为空;所以它确实需要验证.

实际上,拳击没有人们想象的那么糟糕;即使盒装,也将收集gen-0.它可以通过泛型(例如EqualityComparer< T>确实 – 通过一些不同的子类)进行特殊情况,但这看起来有点过分.

JIT也可以删除空检查.我可以在这里说,虽然这经常引用,但我已经看到了无效检查超出JIT删除能力的情况.

网友评论