EqualityComparer<T>.Default isn't clever enough

大兔子大兔子 提交于 2019-12-21 11:37:50

问题


I was reading the source code of EqualityComparer<T>.Default and found that it's not so clever. Here is an example:

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)

The reason is obvious from the source code of the private method in 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>();
}

We can see EqualityComparer<int>.Default,EqualityComparer<MyEnum>.Default and EqualityComparer<long>.Default get a wise comparer whose Equals method looks like:

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
}

The above two are clever, but EqualityComparer<AnotherEnum>.Default is unlucky, from the method we can see at last it gets a ObjectEqualityComparer<T>(), whose Equals method probably looks like:

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
}

I think this condition Enum.GetUnderlyingType(c) == typeof(int) is pointless, if the underlying type of an enum is of type int, the method can convert the default comparer of int to this enum. But why can't an enum based on long? It's not so hard i think? Any special reason? Constructing a comparer like x == y isn't so hard for enum, right? Why at last it gives a slow ObjectEqualityComparer<T> for enums(even it works correctly)?


回答1:


I think that there's simply no compelling reason for the team responsible to add this feature. All features have an implementation cost which includes (among others) the time to document, code and test.

There are a couple of compelling reasons why this particular feature has not been picked over others so far (and will probably never make the cut IMO):

  • It only applies to a very narrow scenario (comparing enums backed by something other than an int, and doing that in some inner loop)
  • There is a very straightforward and discoverable solution if it causes you a problem (write your own comparer)


来源:https://stackoverflow.com/questions/5829441/equalitycomparert-default-isnt-clever-enough

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!