EqualityComparer <T>.默认不够聪明

Che*_*hen 8 .net c# enums equals iequalitycomparer

我正在阅读源代码,EqualityComparer<T>.Default发现它并不那么聪明.这是一个例子:

enum MyEnum : int { A, B }
EqualityComparer<MyEnum>.Default.Equals(MyEnum.A, MyEnum.B)
//is as fast as 
EqualityComparer<int>.Default.Equals(0, 1)

enum AnotherEnum : long { A = 1L, B = 2L }
//is 8x slower than
EqualityComparer<long>.Default.Equals(1L, 2L)
Run Code Online (Sandbox Code Playgroud)

原因很明显来自EqualityComparer中私有方法的源代码.

private static EqualityComparer<T> CreateComparer()
{
    //non-important codes are ignored
    if (c.IsEnum && (Enum.GetUnderlyingType(c) == typeof(int)))
    {
        return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(EnumEqualityComparer<int>), c);
    }
    return new ObjectEqualityComparer<T>();
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到EqualityComparer<int>.Default,EqualityComparer<MyEnum>.DefaultEqualityComparer<long>.Default得到一个明智的比较器,其Equals方法如下:

public static bool Equals(int x, int y)
{
    return x == y;  //or return x.Equals(y); here 
                    //I'm not sure, but neither causes boxing
}

public static bool Equals(MyEnum x, MyEnum y)
{
    return x == y;  //it's impossible to use x.Equals(y) here 
                    //because that causes boxing
}
Run Code Online (Sandbox Code Playgroud)

上面两个是聪明的,但是EqualityComparer<AnotherEnum>.Default运气不好,从最后我们可以看到它得到ObjectEqualityComparer<T>()Equals方法,其方法可能看起来像:

public static bool Equals(AnotherEnum x, AnotherEnum y)
{
    return x.Equals(y);   //too bad, the Equals method is from System.Object
                       //and it's not override, boxing here!
                       //that's why it's so slow
}
Run Code Online (Sandbox Code Playgroud)

我认为这个条件Enum.GetUnderlyingType(c) == typeof(int)没有意义,如果枚举的基础类型是int类型,该方法可以 int的默认比较器转换为此枚举.但为什么不能基于长期的枚举?我觉得这不难吗?任何特殊原因?构建一个比较器x == y对枚举来说并不那么难,对吧?为什么最后它给ObjectEqualityComparer<T>枚举缓慢(即使它正常工作)?

Jon*_*Jon 6

我认为负责添加此功能的团队没有令人信服的理由.所有功能都有一个实现成本,其中包括(其中包括)文档,代码和测试的时间.

有几个令人信服的理由说明为什么到目前为止这个特定功能还没有被其他人选中(并且可能永远不会削减IMO):

  • 它只适用于一个非常狭窄的场景(比较enums一个除了a之外的东西int,并在一些内部循环中执行此操作)
  • 如果它导致您出现问题,可以使用非常直接且可发现的解决方案(编写您自己的比较器)