繁体   English   中英

平等比较器<t> .Default 不够聪明</t>

[英]EqualityComparer<T>.Default isn't clever enough

我正在阅读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)

原因从 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>();
}

我们可以看到EqualityComparer<int>.DefaultEqualityComparer<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
}

上面这两个是聪明的,但是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
}

我认为这个条件Enum.GetUnderlyingType(c) == typeof(int)是没有意义的,如果枚举的底层类型是 int 类型,该方法可以int 的默认比较器转换为这个枚举。 但是为什么不能基于 long 的枚举呢? 我想这不是那么难吗? 有什么特殊原因吗? 构造一个像x == y这样的比较器对于枚举来说并不难,对吧? 为什么最后它为枚举提供了一个缓慢的ObjectEqualityComparer<T> (即使它工作正常)?

我认为负责添加此功能的团队根本没有令人信服的理由。 所有功能都有实现成本,其中包括(除其他外)记录、编码和测试的时间。

有几个令人信服的原因可以解释为什么这个特定的功能到目前为止还没有被选中(并且可能永远不会成为 IMO 的切入点):

  • 它仅适用于非常狭窄的场景(比较由int以外的其他东西支持的enums ,并在某个内部循环中执行此操作)
  • 如果它给您带来问题,有一个非常简单且可发现的解决方案(编写您自己的比较器)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM