我认为是时候将之前的答案实现更新为 .Net4.0+,由于 IEqualityComparer<in T> 接口上的逆变性,不再需要泛型:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
public sealed class ReferenceEqualityComparer
: IEqualityComparer, IEqualityComparer<object>
{
private ReferenceEqualityComparer() { }
public static readonly ReferenceEqualityComparer Default
= new ReferenceEqualityComparer();
public /*new*/ bool Equals(object x, object y)
{
return x == y; // This is reference equality! (See explanation below)
}
public int GetHashCode(object obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
现在只需要存在一个用于所有引用相等检查的实例,而不是像以前那样为每个类型T 存在一个。
您不再需要在每次想要使用它时都指定T,并且还避免了不必要的通用运行时类型的污染。
至于x == y为什么是引用相等,是因为==operator是一个静态方法,也就是说它在编译时被解析,而在编译时x和y参数类型为object。
事实上这就是Object.ReferenceEquals(object, object)方法sourcecode的样子:
public static bool ReferenceEquals(object objA, object objB) {
return objA == objB;
}
为不熟悉Covariance and Contravariance概念的人澄清一下...
class MyClass
{
ISet<MyClass> setOfMyClass = new HashSet<MyClass>(ReferenceEqualityComparer.Default);
}
...上面的代码编译;请注意,它确实不说HashSet<object>。