问题
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.
回答1:
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.
回答2:
I end up using this solution also as I could not find any workaround.
To fix the non thread safe implementation, you could easily use a static initiailizer.
public static ReferenceComparer<T> Instance => new ReferenceComparer<T>();
(sorry for the answer instead of a comment to up-voted thread, I have a new account with no comment rights, yet).
来源:https://stackoverflow.com/questions/4901320/is-there-any-kind-of-referencecomparer-in-net