18

BCL 中有几个地方可以使用IEqualityComparer。像Enumerable.ContainsDictionary Constructor如果我对默认的比较器不满意,我可以提供我的比较器。

有时我想知道集合是否包含我引用的那个对象。不是在任何其他意义上被视为“平等”的那个。
问题是: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.ContainsDictionary开心。

4

2 回答 2

17

据我所知,BCL 没有公开任何IEqualityComparer<T>从 .NET 4.0 开始实现引用相等的公共类型。

但是,似乎确实有很多内部类型可以做到这一点,例如:

  • System.Dynamic.Utils.ReferenceEqualityComparer<T> (在 System.Core 中)
  • System.Xaml.Schema.ReferenceEqualityComparer<T> (在 System.Xaml 中)。

我用反射器查看了这两种类型的实现,您会很高兴知道它们似乎都以与您的几乎相同的方式实现,除了它们不使用延迟初始化对于静态实例(他们在类型的静态构造函数中创建它)。

对于您的实现,我能想到的唯一可能的“问题”是延迟初始化不是线程安全的,但是由于实例“便宜”并且没有保持任何状态,因此不应产生任何错误或重大问题性能问题。但是,如果您想强制执行单例模式,则必须正确执行。

于 2011-02-04T18:09:19.280 回答
2

我最终也使用了这个解决方案,因为我找不到任何解决方法。

要修复非线程安全的实现,您可以轻松使用静态初始化程序。

public static ReferenceComparer<T> Instance => new ReferenceComparer<T>();

(对不起,我有一个没有评论权的新帐户,而不是对投票的评论发表评论)。

于 2015-12-16T07:13:30.087 回答