Note that there are some explanatory texts on larger screens.

plurals
  1. POEqualityComparer<T>.Default isn't clever enough
    primarykey
    data
    text
    <p>I was reading the source code of <code>EqualityComparer&lt;T&gt;.Default</code> and found that it's not so clever. Here is an example:</p> <pre><code>enum MyEnum : int { A, B } EqualityComparer&lt;MyEnum&gt;.Default.Equals(MyEnum.A, MyEnum.B) //is as fast as EqualityComparer&lt;int&gt;.Default.Equals(0, 1) enum AnotherEnum : long { A = 1L, B = 2L } //is 8x slower than EqualityComparer&lt;long&gt;.Default.Equals(1L, 2L) </code></pre> <p>The reason is obvious from the source code of the private method in EqualityComparer.</p> <pre><code>private static EqualityComparer&lt;T&gt; CreateComparer() { //non-important codes are ignored if (c.IsEnum &amp;&amp; (Enum.GetUnderlyingType(c) == typeof(int))) { return (EqualityComparer&lt;T&gt;) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(EnumEqualityComparer&lt;int&gt;), c); } return new ObjectEqualityComparer&lt;T&gt;(); } </code></pre> <p>We can see <code>EqualityComparer&lt;int&gt;.Default</code>,<code>EqualityComparer&lt;MyEnum&gt;.Default</code> and <code>EqualityComparer&lt;long&gt;.Default</code> get a wise comparer whose <code>Equals</code> method looks like:</p> <pre><code>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 } </code></pre> <p>The above two are <em>clever</em>, but <code>EqualityComparer&lt;AnotherEnum&gt;.Default</code> is unlucky, from the method we can see at last it gets a <code>ObjectEqualityComparer&lt;T&gt;()</code>, whose <code>Equals</code> method probably looks like:</p> <pre><code>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 } </code></pre> <p>I think this condition <code>Enum.GetUnderlyingType(c) == typeof(int)</code> is pointless, if the underlying type of an enum is of type int, the method can <em>convert</em> 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 <code>x == y</code> isn't so hard for enum, right? Why at last it gives a slow <code>ObjectEqualityComparer&lt;T&gt;</code> for enums(even it works correctly)?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload