BCL中有几个地方可以使用IEqualityComparer。与Enumerable.Contains或Dictionary Constructor一样。如果我对default不满意,我可以提供我的比较器。
有时我想知道该集合是否包含我引用的那个对象。不是任何其他意义上被认为是“平等”的那个 问题是: BCL中是否存在仅依赖ReferenceEquals方法的标准相等比较器?
我自己写的是:
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);
}
}
我没有彻底测试它,也没有考虑很多场景,但似乎让Enumerable.Contains
和Dictionary
非常高兴。
答案 0 :(得分:17)
据我所知,自.NET 4.0起,BCL不会公开任何实现IEqualityComparer<T>
引用相等的公共类型。
但是,似乎有许多内部类型可以执行此操作,例如:
System.Dynamic.Utils.ReferenceEqualityComparer<T>
(在System.Core中)System.Xaml.Schema.ReferenceEqualityComparer<T>
(在System.Xaml中)。我用反射器看了这两种类型的实现,你会很高兴知道这两种类型的实现方式实际上与你的相同,除了它们不对静态实例使用延迟初始化(它们在类型的静态构造函数中创建它)。
我能用你的实现想到的唯一可能的“问题”是懒惰初始化不是线程安全的,但由于实例是“便宜的”并且没有保持任何状态,所以不应该创建任何状态错误或主要性能问题。如果你想强制执行单例模式,你必须正确地进行。
答案 1 :(得分:2)
我最终也使用此解决方案,因为我找不到任何解决方法。
要修复非线程安全实现,您可以轻松使用静态初始化器。
public static ReferenceComparer<T> Instance => new ReferenceComparer<T>();
(抱歉答案而不是对投票通知的评论,我有一个没有评论权的新帐户)。