如何检索枚举的哈希码而不将其装箱?

本文关键字:哈希码 何检索 检索 枚举 | 更新日期: 2023-09-27 17:49:38

如果枚举存储在聚合类型中,则可能希望将其包含在该类型的散列代码中(假设是典型的"乘以素数"散列函数)。如果只调用SomeEnum.GetHashCode(),则JIT会将实例装箱,即使在发布版本中也是如此。

分析显示,我的应用程序大约有10%的时间花在各种GetHashCode函数内的装箱枚举上。

几个值类型实现IEquatable或类似的接口,这允许调用GetHashCode作为静态方法;这样就避免了拳击。但是System.Enum不提供GetHashCode的静态过载。有没有一种计算代码的方法可以避免装箱?

如何检索枚举的哈希码而不将其装箱?

可以转换为枚举的底层类型(通常是int,除非枚举定义另有规定),并使用该类型的覆盖GetHashCode()方法。

enum TestEnum
{
    Test1,
    Test2
}
TestEnum t = TestEnum.Test1;
((int)t).GetHashCode(); // no boxing
t.GetHashCode(); // boxing

下面是这个代码的IL:

IL_0000:  nop
IL_0001:  ldc.i4.0
IL_0002:  stloc.0
IL_0003:  ldloc.0
IL_0004:  stloc.1
IL_0005:  ldloca.s   V_1
IL_0007:  call       instance int32 [mscorlib]System.Int32::GetHashCode()
IL_000c:  pop
IL_000d:  ldloc.0
IL_000e:  box        ConsoleApplication1.Program/TestEnum
IL_0013:  callvirt   instance int32 [mscorlib]System.Object::GetHashCode()
IL_0018:  pop
IL_0019:  ret

编辑:为了完整起见,我应该指出int.GetHashCode()的主体只是return this;,所以正如Raymond Chen在上面的评论中指出的那样,简单地将enum转换为int就足以获得哈希码。