我读 EqualityComparer&LT的来源$ C $ C; T> .DEFAULT
,发现它不是那么聪明。下面是一个例子:
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)
原因是从EqualityComparer私有方法的来源$ C $ C明显。
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>();
}
我们可以看到 EqualityComparer&LT; INT&GT; .DEFAULT
, EqualityComparer&LT; MyEnum&GT; .DEFAULT
和 EqualityComparer&LT;长&GT; .DEFAULT
获得一个明智的比较器,其等于
的方法是这样的:
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
}
以上两者的聪明的,但 EqualityComparer&LT; AnotherEnum&GT; .DEFAULT
是不吉利的,从方法,我们终于可以看到它得到 ObjectEqualityComparer&LT; T&GT;()
,其等于
办法大概是这样的:
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
}
我觉得这个条件 Enum.GetUnderlyingType(三)== typeof运算(INT)
是没有意义的,如果一个枚举的基础类型是int类型,该方法可转换的INT的默认比较于此枚举。但是,为什么不能枚举基于长?这不是那么难,我认为?任何特别的原因吗?构建像一个比较器x ==是
不是这么难枚举,对不对?为什么最后它给出了一个缓慢的 ObjectEqualityComparer&LT; T&GT;
的枚举(即使它正常工作)
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)?
我认为,根本没有令人信服的理由,负责添加此功能的小组。所有的功能都实现成本,这包括(其中包括)来记录时间,code和测试。
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.
有几个令人信服的理由,为什么这个特殊的功能还没有被挑过别人,到目前为止(而且可能永远不会获得晋级IMO):
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):
这仅适用于很窄的情况下(比较枚举
一个不是 INT
,并做一些其他的支持在一些内环)
有一个非常简单的和发现的解决方案,如果它使你(写自己的比较器)问题
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)