首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ReferenceEquals的IEqualityComparer<T>

使用ReferenceEquals的IEqualityComparer<T>
EN

Stack Overflow用户
提问于 2009-12-12 02:40:47
回答 5查看 9.1K关注 0票数 64

是否有使用ReferenceEquals的默认IEqualityComparer<T>实现

EqualityComparer<T>.Default使用ObjectComparer,后者使用object.Equals()。在我的例子中,对象已经实现了IEquatable<T>,我只需要忽略它并通过对象的引用进行比较。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-12-12 03:09:54

以防没有默认的实现,这是我自己的:

由280Z28编辑:使用RuntimeHelpers.GetHashCode(object)的基本原理,你们中的许多人可能以前没有见过。:)此方法有两个效果,使其成为此实现的正确调用:

  1. 当对象为null时,它返回0。由于ReferenceEquals适用于空参数,因此比较器的GetHashCode().
  2. It实现也应该以非虚拟方式调用Object.GetHashCode()ReferenceEquals特别忽略Equals的任何覆盖,因此GetHashCode()的实现应该使用与ReferenceEquals的效果匹配的特殊方法,这正是RuntimeHelpers.GetHashCode的用途。

完280Z28

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

/// <summary>
/// A generic object comparerer that would only use object's reference, 
/// ignoring any <see cref="IEquatable{T}"/> or <see cref="object.Equals(object)"/>  overrides.
/// </summary>
public class ObjectReferenceEqualityComparer<T> : EqualityComparer<T>
    where T : class
{
    private static IEqualityComparer<T> _defaultComparer;

    public new static IEqualityComparer<T> Default
    {
        get { return _defaultComparer ?? (_defaultComparer = new ObjectReferenceEqualityComparer<T>()); }
    }

    #region IEqualityComparer<T> Members

    public override bool Equals(T x, T y)
    {
        return ReferenceEquals(x, y);
    }

    public override int GetHashCode(T obj)
    {
        return RuntimeHelpers.GetHashCode(obj);
    }

    #endregion
}
票数 61
EN

Stack Overflow用户

发布于 2016-02-20 15:01:01

我认为是时候将以前的answers实现更新为.Net4.0+了,由于IEqualityComparer<in T>接口上的矛盾,不再需要泛型:

代码语言:javascript
复制
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是引用相等,这是因为==操作符是一个静态方法,这意味着它是在编译时解析的,而在编译时xy参数是object类型。

实际上,这就是Object.ReferenceEquals(object, object) method source code的样子:

代码语言:javascript
复制
public static bool ReferenceEquals(object objA, object objB) {
    return objA == objB;
}

为了向那些不熟悉Covariance and Contravariance概念的人澄清...

代码语言:javascript
复制
class MyClass
{
    ISet<MyClass> setOfMyClass = new HashSet<MyClass>(ReferenceEqualityComparer.Default);
}

上面的代码会编译;请注意,它没有说...the HashSet<object>

票数 20
EN

Stack Overflow用户

发布于 2016-12-16 00:56:30

下面是C# 6和更高版本的一个简单实现:

代码语言:javascript
复制
public sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer<object>
{
    public static ReferenceEqualityComparer Default { get; } = new ReferenceEqualityComparer();

    public new bool Equals(object x, object y) => ReferenceEquals(x, y);
    public int GetHashCode(object obj) => RuntimeHelpers.GetHashCode(obj);
}

或者确保它只能与引用类型一起使用的泛型版本:

代码语言:javascript
复制
public sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class
{
    public static IEqualityComparer<T> Default { get; } = new ReferenceEqualityComparer<T>();

    public bool Equals(T x, T y) => ReferenceEquals(x, y);
    public int GetHashCode(T obj) => RuntimeHelpers.GetHashCode(obj);
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1890058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档