我正在阅读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的默认比较器转换为此枚举.但为什么不能基于长期的枚举?我觉得这不难吗?任何特殊原因?构造像x == y这样的比较器对枚举来说并不那么难,对吧?为什么最后它给出了一个慢的ObjectEqualityComparer< T>对于枚举(即使它正常工作)?