在不知道对象类型的情况下比较两个对象数组

本文关键字:对象 两个 数组 比较 不知道 类型 情况下 | 更新日期: 2023-09-27 18:16:17

我需要你的帮助!我想比较两个对象数组。这些数组应该是相同的,但顺序不相等。

背景:

我正在写一个函数来比较相同类型的对象树。通过反射,我用第二个对象检查第一个对象的每个属性,当:

  • 我找到一个基本类型,我比较它,如果发现差异I

  • 我找到一个对象,我在两个对象上(递归地)调用方法

  • 我找到一个数组,我检查长度,如果它们是相同的,我解析数组并将每个值与方法进行比较(递归地)。在这种情况下,我需要排序数组,以确保对象是在相同的顺序

我想的方式,但无法实现:

  • 我不能重写类的equals方法,有太多了

  • 我尝试在IComparer接口中使用GetHashCode,但是

你知道我该怎么做吗?我正在考虑生成基于内容的HashCode,但我如何才能做到这一点?

谢谢你的帮助。

在不知道对象类型的情况下比较两个对象数组

我找到了这个解决方案…

我实现了一个IComparer,并比较我的对象从流转换为字符串(不那么优雅,但它工作得很好):

    private class ObjectStreamComp : IComparer
    {
        public int Compare(Object x, Object y )  
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream mx = new MemoryStream())
            using (MemoryStream my = new MemoryStream())
            {
                binaryFormatter.Serialize(mx, x);
                binaryFormatter.Serialize(my, y);
                mx.Position = 0;
                my.Position = 0;
                return (new StreamReader(mx)).ReadToEnd().CompareTo((new StreamReader(my)).ReadToEnd());
            }   
        }
    }

我可以使用序列化,因为我的对象树被标记为序列化(用于XML序列化)。

我是这样用的:

Array.Sort(valueReferenceArray, ((IComparer)new ObjectStreamComp()));
Array.Sort(valueCreatedArray, ((IComparer)new ObjectStreamComp()));

在这种情况下,你可以实现你自己的IEqualityComparer

public class MyComparer<T> : IEqualityComparer<T> where T : class
{        
    public bool Equals(T x, T y)
    {
        //your code here
    }
    public int GetHashCode(T obj)
    {
        return obj.GetHashCode();
    }
}

例如,如果你想在except中使用它你只需这样做

var list1 = new List<object>();
var list2 = new List<object>();
var rest = list1.Except(list2, new MyComparer<object>());

您知道,如果性能出现问题,仅使用反射比较两个对象树将会给您带来麻烦。在任何可能的情况下,您都应该尽量避免反射,特别是在处理大型对象树时。对于概念验证来说,反射是可以的,但对于更广泛的应用就不行了。

但是重写Equals-Method有什么错?XSD通常不生成equals方法,因此您可以使用部分类自由地用自己的东西扩展这些生成的类。这正是创建部分类的目的,以便更容易地生成静态和生成代码。

Edit:注意,如果你重写Equals,你也必须适当地重写GetHashCode。然而,这意味着所有使用您的类的对象默认情况下都将使用值相等。如果这不是你想要的,Alex Pashkin建议的自定义IEqualityComparer是一个更好的选择。