我正在阅读源代码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
and 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
}
以上两个是clever, but EqualityComparer<AnotherEnum>.Default
运气不好,从方法上我们可以看到最后得到了一个ObjectEqualityComparer<T>()
, whose 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 类型,则该方法可以convertint 与此枚举的默认比较器。但为什么枚举不能基于 long 呢?我想这并不难?有什么特殊原因吗?构建一个类似的比较器x == y
对于 enum 来说并不难,对吧?为什么最后它给出了一个缓慢的ObjectEqualityComparer<T>
对于枚举(即使它工作正常)?