Search code examples
c#.netcomparisonbase-class-library

Is there any kind of "ReferenceComparer" in .NET?


There are several places in BCL where one can make use of IEqualityComparer. Like Enumerable.Contains or Dictionary Constructor. I can provide my comparer if I'm not happy with the default one.

Sometimes I want to know whether the collection contains that very object that I have reference to. Not the one that is considered "equal" in any other meaning.
The question is: whether there exists standard equality comparer in the BCL that relies only on ReferenceEquals method?

The one that I wrote myself is this:

class ReferenceComparer<T> : IEqualityComparer<T> where T : class
{
    private static ReferenceComparer<T> m_instance;

    public static ReferenceComparer<T> Instance
    {
        get
        {
            return m_instance ?? (m_instance = new ReferenceComparer<T>());
        }
    }

    public bool Equals(T x, T y)
    {
        return ReferenceEquals(x, y);
    }

    public int GetHashCode(T obj)
    {
        return RuntimeHelpers.GetHashCode(obj);
    }
}

I didn't test it thoroughly nor considered lots of scenarios, but it seems to make Enumerable.Contains and Dictionary pretty happy.


Solution

  • As far as I know, the BCL doesn't expose any public types that implement IEqualityComparer<T> with reference-equality as of .NET 4.0 .

    However, there do appear to be a bunch of internal types that do this, such as:

    • System.Dynamic.Utils.ReferenceEqualityComparer<T> (in System.Core)
    • System.Xaml.Schema.ReferenceEqualityComparer<T> (in System.Xaml).

    I took a look at the implementations of these two types with reflector, and you'll be happy to know that both of them appear to be implemented in a way that is virtually identical to yours, except that they don't use lazy-initialization for the static instance (they create it in the static constructor for the type).

    The only possible 'issue' I can think of with your implementation is that the lazy-initialization is not thread-safe, but since instances are 'cheap' and aren't holding onto any state, that shouldn't create any bugs or major performance problems. If you want to enforce the singleton-pattern though, you'll have to do it properly.