EqualityComparer <T> .Predeterminado no es lo suficientemente inteligente
Estaba leyendo el código fuente deEqualityComparer<T>.Default
y descubrí que no es tan inteligente. Aquí hay un ejemplo
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)
La razón es obvia por el código fuente del método privado en 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>();
}
Podemos verEqualityComparer<int>.Default
,EqualityComparer<MyEnum>.Default
yEqualityComparer<long>.Default
consiga un comparador sabio cuyaEquals
l método @ se ve así:
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
}
Los dos anteriores soninteligent, peroEqualityComparer<AnotherEnum>.Default
no tiene suerte, por el método que podemos ver finalmente se obtiene unObjectEqualityComparer<T>()
, cuyoEquals
l método @ probablemente se parece a:
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
}
Creo que esta condiciónEnum.GetUnderlyingType(c) == typeof(int)
no tiene sentido, si el tipo subyacente de una enumeración es de tipo int, el método puedeconverti el comparador predeterminado de int para esta enumeración. Pero, ¿por qué no puede una enumeración basada en mucho tiempo? No es tan difícil, creo? ¿Alguna razón especial? Construyendo un comparador comox == y
no es tan difícil para la enumeración, ¿verdad? ¿Por qué al fin da una @ lenObjectEqualityComparer<T>
para enumeraciones (incluso si funciona correctamente)