泛型类型约束为class时CIL出现box操作的原因咨询
为什么约束为
class的泛型方法会生成box指令? 首先看你编写的C#代码:
public static bool EquivalentTo<T>(this T? current, T? compare) where T : class { if (current is null && compare is null) // both are null return true; if (current is null || compare is null) // one is null, but not both return false; return current.Equals(compare); }
针对生成的CIL中出现的多次box !!T操作,原因主要有以下几点:
1. is null编译的通用代码路径
C#编译器处理泛型参数的is null判断时,并没有针对class约束的场景单独生成特殊逻辑,而是走了统一的代码生成路径:将泛型参数装箱为object后再判断是否为null。
虽然对于引用类型来说,直接判断引用是否为null不需要装箱(引用类型的null在IL层面可直接对比),但编译器当前实现没有区分值类型和引用类型泛型的is null处理逻辑,因此统一生成了装箱指令。
2. 调用Object.Equals(object)的参数转换需求
最后一行的current.Equals(compare),编译器默认解析为调用System.Object.Equals(object)虚方法(在没有显式Equals(T)重载的情况下)。该方法的参数类型是object,编译器因此生成了将!!T转换为object的指令——尽管引用类型泛型参数可直接隐式转换为object(无需装箱),但通用代码生成逻辑并未做此区分,所以生成了box指令。
3. JIT会优化冗余的box操作
无需担心性能损耗:.NET的JIT编译器在运行时会识别出T是class约束的引用类型,此时box !!T属于完全冗余的操作(引用类型装箱不会改变其引用值),会被JIT直接优化掉,不会实际执行装箱动作,运行时性能和无box指令的情况完全一致。
内容的提问来源于stack exchange,提问作者IamIC
相关产品推荐
相关产品推荐

