のソースコードを読んで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
}
上記の 2 つは賢いですが、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 のデフォルトの比較子をこの列挙型に変換できます。しかし、なぜ long に基づく列挙型を使用できないのでしょうか? そんなに難しくないですよね?何か特別な理由は?のような比較子を構築するx == y
ことは、列挙型にとってそれほど難しくありませんよね? ついにObjectEqualityComparer<T>
列挙型の速度が低下するのはなぜですか(正しく動作しても)?