Я читал исходный код 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>.Default
, EqualityComparer<MyEnum>.Default
и EqualityComparer<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 для этого перечисления.Но почему enum не может основываться на long?Это не так сложно, я думаю?Есть особая причина?Создание сравнения как x == y
не так сложно для enum, верно?Почему, наконец, он дает медленный ObjectEqualityComparer<T>
для перечислений (даже он работает правильно)?