Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 318
alpha-mouse Avatar asked Feb 04 '11 18:02

alpha-mouse


1 Answers

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.

like image 68
Ani Avatar answered Oct 30 '22 22:10

Ani