c# - 测试对象相等性的最佳方法是什么 - 无需覆盖 Equals 和 GetHashCode,或实现 IEquatable<T>?

标签 c# equality

我想检查两个没有公共(public)属性的对象是否相等。但是,我不想覆盖 Equals & GetHashCode 方法,或实现 IEquatable。例如,考虑以下代码:

class Program
{
    static void Main(string[] args)
    {
        Guid id = Guid.NewGuid();
        string personName = "MyName";
        MyClass object1 = new MyClass(id, personName);
        MyClass object2 = new MyClass(id, personName);
        //This returns false, but I'd like it to return true:
        Console.WriteLine(object1.Equals(object2));
        //[edit]...by using, for example:
        Console.WriteLine(ObjectsAreEqual(object1, object2));
    }
}

class MyClass
{
    private Guid _id;
    private string _personName;
    public MyClass(Guid id, string personName)
    {
        _id = id;
        _personName = personName;
    }
}

我知道标准方法是重写 Equals & GetHashCode,但出于各种原因,我不想更改类中的任何代码。另外,没有公共(public)属性(property),所以我无法比较这些。还有其他实现方法吗?

例如,通过反射?或者可能通过将对象序列化为 JSON,然后比较生成的字符串?

谢谢。

最佳答案

您无法更改 Equals 的结果实例方法而不覆盖它。所以你需要使用 IEqualityComparer<T>需要将其显式传递给需要进行相等性检查的代码。幸运的是,大多数内置集合接受这样的相等比较器作为其构造函数的参数。

实现 IEqualityComparer<T>如果您不想以任何方式更改原始类,那么使用反射似乎是您唯一的选择。

您可以获得FieldInfo使用 GetField("_personName",BindingFlags.NonPublic)然后调用GetValue在它上面获取值。

void Main()
{
        Guid id = Guid.NewGuid();
        string personName = "MyName";
        MyClass object1 = new MyClass(id, personName);
        MyClass object2 = new MyClass(id, personName);
        //This returns false, but I'd like it to return true:
        Console.WriteLine(object1.Equals(object2));
        //[edit]...by using, for example:
        Console.WriteLine(MyClassEqualityComparer.Instance.Equals(object1, object2));
}

public class MyClass
{
    private Guid _id;
    private string _personName;
    public MyClass(Guid id, string personName)
    {
        _id = id;
        _personName = personName;
    }
}

public class MyClassEqualityComparer:IEqualityComparer<MyClass>
{
  private static FieldInfo personNameField=typeof(MyClass).GetField("_personName",BindingFlags.Instance|BindingFlags.NonPublic);
  private static FieldInfo idField=typeof(MyClass).GetField("_id",BindingFlags.Instance|BindingFlags.NonPublic);

  public bool Equals(MyClass o1,MyClass o2)
  {
    if(o1==o2)
      return true;
    if(o1==null||o2==null)
      return false;
    string name1=(string)personNameField.GetValue(o1);
    string name2=(string)personNameField.GetValue(o2);
    if(name1!=name2)
      return false;
    Guid id1=(Guid)idField.GetValue(o1);
    Guid id2=(Guid)idField.GetValue(o2);
    return id1==id2;
  }

  public int GetHashCode(MyClass o)
  {
    if(o==null)
      return 0;
    string name=(string)personNameField.GetValue(o);
    Guid id=(Guid)idField.GetValue(o);
    return name.GetHashCode()^id.GetHashCode();
  }

  private MyClassEqualityComparer()
  {
  }

  public static readonly IEqualityComparer<MyClass> Instance=new MyClassEqualityComparer();
}

关于c# - 测试对象相等性的最佳方法是什么 - 无需覆盖 Equals 和 GetHashCode,或实现 IEquatable<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7738514/

相关文章:

python - != 和 <> 有什么区别?

java - 为什么 "=="对于整数和字符串引用的工作方式不同?

c# - 微软报告 : Setting subreport parameters in code

c# - 在功能列表操作中,我们怎么称呼 "inserting something between each item"?

c# - 正则表达式检测字符串中的Javascript

scala - scala 中 null 的相等性,odersky 书的解释似乎与 scala 代码不同?

javascript - 我可以让 Visual Studio 2008 中的 C# 代码编辑器显示行分隔方法吗?

c# - .NET 中更快(不安全)的 BinaryReader

c++ - std::equal_to 对于浮点类型是否可靠?

c - 在 C 中使用 while() 测试不等式