确定未知类型的相等性

时间:2016-08-23 06:56:32

标签: c# .net observablecollection iequalitycomparer data-compression

我需要检查给定的实例是否与集合匹配(两者都是未知类型)。

看看

void Main()
{
    // Employee "John" Object got from Service Layer #1
    Object obj1 = Client1.GetObject("John");

    // Employee "John" Object got from Service Layer #2
    Object obj2 = Client2.GetObject("John");

    bool flag = CheckEquality(obj1, obj2); // Both objects are Unknown Type
}

平等检查方法:

public bool CheckEquality(object obj1, object obj2)
{
    // Solution for Determining equality for unknown types
}

例如 - 考虑以下代码:(仅用于理解目的)

情景#1

public class EmpPerson
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
}

obj1 保留实例new EmpPerson() { ID = 1, Name = "John", Address = "Los Angeles" };

obj2 保留实例new EmpPerson() { ID = 1, Name = "John", Address = "Los Angeles" };

情景#2

obj1 保留值"John Smith"

obj2 保留值"John Smith"

情景#3

obj1 保留值"John Smith"

obj2 保留实例new EmpPerson() { ID = 1, Name = "John", Address = "Los Angeles" };

情景#4

obj1 保留值new UnknownTypeA()

obj2 保留值new UnknownTypeX()

我需要检查两个对象是否相同。

请帮助我。如何检查未知类型的相等性。

4 个答案:

答案 0 :(得分:1)

好的我觉得你在这里缺少一些要点......

首先,你的平等意味着什么?

当两个对象持有相同的引用时是否相等? 当他们拥有相同的共同财产时,他们是平等的吗? 还是什么时候?

第二个(也许更重要),为什么你需要检查你不知道的对象是否相等?

如果你甚至不知道对象的类型,那说他们的等同点是什么?你甚至不能使用它们......

如果您知道对象的类型,那么您就知道如何比较它们。

您添加了方案案例#4,为什么在您不知道任何类型时比较不同类型的两个对象?

在OOP中,您无法比较不同类型的对象,因为它没有意义,您无法比较苹果和梨......

这就是为什么我们通常创建包含不同类型的公共部分的接口,或者我们创建方法来将对象类型转换为另一个。

我在这里给出的解决方案意味着您可以控制对象的实现。

您可能希望重载Equals()方法(从Object继承)。

public class EmpPerson
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public override bool Equals(object obj)
    {
        EmpPerson cmp = (EmpPerson)obj;
        return ID.Equals(cmp.ID);
    }
}

无论何时你需要比较它们:

obj1.Equals(obj2);

然而,这带来了对象需要具有相同类型的限制,无论类型如何。

注意:此处尚未执行错误检查,您需要执行此操作...

答案 1 :(得分:1)

您可以查看Compare-Net-Objects deep equals library,它可用于通过反射对对象进行深度比较。

答案 2 :(得分:1)

此代码将按类型和公共字段列表进行比较而不使用recoursion对象。它可以通过添加recoursion和属性来改进。但是对于所有案例而言,它都不是解决方案。

bool AreEquals(object a, object b)
{
  if (a == null && b == null) return true;
  if (a == null || b == null) return false;      

  var typeA = a.GetType();
  var typeB = b.GetType();

  if (typeA.Equals(typeB)) return a.Equals(b);

  var fieldsA = typeA.GetFields().Where(field => field.IsPublic).ToArray();
  var fieldsB = typeB.GetFields().Where(field => field.IsPublic).ToArray();

  if (fieldsA.Length != fieldsB.Length) return false;

  foreach(var field in fieldsA)
  {
     var other = fieldsB.FirstOrDefault(f => f.FieldType.Equals(field.FieldType) && f.Name.Equals(field.Name));
     if (other == null) return false;

     if (!field.GetValue(a).Equals(other.GetValue(b))) return false;  
  }

  return true;
}

答案 3 :(得分:0)

另一种可能性是序列化对象并比较序列化输出。

Binary serialization for deep object comparison

这可以是二进制或xml,或者其他。这是非常通用的,您可以使用开箱即用的实用程序来影响序列化行为。