C#中的复杂对象比较

时间:2009-12-11 19:02:53

标签: c#

我有两个相同类型的复杂对象。我想比较两个对象,以确定它们是否具有完全相同的值。这样做的有效方法是什么?

下面给出的样本类结构:

class Package
{
    public List<GroupList> groupList;
}
class GroupList
{
   public List<Feature> featurelist;
}
class Feature
{
   public int qty;
}

8 个答案:

答案 0 :(得分:5)

好的,所以你想要深度无序的结构比较。 “无序”部分很棘手,事实上它强烈暗示你的类设计不正确:List<T>本身是有序的,所以也许你宁愿在那里使用HashSet<T>(如果你不希望有任何重复)。这样做会使比较更容易实现,并且更快(虽然插入会更慢):

class Package
{
    public HashSet<GroupList> groupList;

    public override bool Equals(object o)
    {
        Package p = o as Package;
        if (p == null) return false;
        return groupList.SetEquals(p.groupList);
    }

    public override int GetHashCode()
    {
        return groupList.Aggregate(0, (hash, g) => hash ^ g.GetHashCode());
    }
}

class GroupList
{
   public HashSet<Feature> featureList;

    public override bool Equals(object o)
    {
        GroupList g = o as GroupList;
        if (g == null) return false;
        return featureList.SetEquals(g.featureList);
    }

    public override int GetHashCode()
    {
        return featureList.Aggregate(0, (hash, f) => hash ^ f.GetHashCode());
    }
}

class Feature
{
    public int qty;

    public override bool Equals(object o)
    {
        Feature f = o as Feature;
        if (f == null) return false;
        return qty == f.qty;
    }

    public override int GetHashCode()
    {
        return qty.GetHashCode();
    }
}

如果你想继续使用List<T>,你需要使用LINQ集操作 - 但请注意,这些操作要慢得多:

class Package
{
    public List<GroupList> groupList;

    public override bool Equals(object o)
    {
        Package p = o as Package;
        if (p == null) return false;
        return !groupList.Except(p.groupList).Any();
    }
}

class GroupList
{
   public List<Feature> featureList;

    public override bool Equals(object o)
    {
        GroupList g = o as GroupList;
        if (g == null) return false;
        return !featureList.Except(f.featureList).Any();
    }
}

答案 1 :(得分:2)

对于复杂对象,我会考虑运算符重载。

在重载运算符上,我将定义我的条件是否相等。

http://msdn.microsoft.com/en-us/library/aa288467%28VS.71%29.aspx

答案 2 :(得分:2)

我们总是最终在类上编写一个方法,通过一切并比较它。您可以将其实现为IComparable,或覆盖Equals。

答案 3 :(得分:2)

正如评论所说,取决于你想要衡量的“准确”程度。

您可以只覆盖相等并实现GetHashCode方法,但这并不能保证它们是完全匹配。但是会确保它们“极有可能”完全匹配。

接下来你可以做的是遍历类中的每个属性/字段并比较这些哈希值。这将“非常可能”完全匹配。

要真正获得完全匹配,您必须在递归循环中比较每个字段和成员...不推荐。

答案 4 :(得分:1)

如果我是你,我会在两种类型上实现IComparable接口:

http://msdn.microsoft.com/en-us/library/system.icomparable.aspx

从那里你可以使用.CompareTo,并在你的情况下实现所需的精确比较。这是.NET中的一般最佳实践,我认为适用于您的情况。

答案 5 :(得分:1)

取决于你想要做什么比较。像其他人一样指出IComparer是一个不错的选择。如果你打算使用lambdas和LINQ,我会使用IEqualityComparer

http://msdn.microsoft.com/en-us/library/system.collections.iequalitycomparer.aspx

答案 6 :(得分:1)

一般情况下,无论是否重载等于,都需要一种检查二者的方法,或者使用IComparer。

你问过如何最有效地做到这一点,这里有一些提示:

  • 你的平等方法应该尽快放弃,例如检查列表的大小是否相同,如果不是,则立即返回false
  • 如果你可以实现一个有效的hashCode,你可以先比较哈希,如果它们不相等那么对象不相等,如果它们相等,那么你需要比较对象以查看对象是否相等< / LI>

因此,一般来说,首先进行最快的比较以尝试返回false。

答案 7 :(得分:0)

使用反射,这是一种稍微简化的方法。您可能需要为特定比较添加其他数据类型检查或循环列表等,但这应该可以帮助您入门。

void Mymethod(){

Class1 class1 = new Class1();

//define properties for class1

Class1 class2 = new Class1();
//define properties for class2

PropertyInfo[] properties = class1.GetType().GetProperties();

bool bClassesEqual = true;

foreach (PropertyInfo property in properties)
{
    Console.WriteLine(property.Name.ToString());

    if (property.GetValue(class1, null) != property.GetValue(class2, null))
    {
        bClassesEqual = false;
        break;

    }

}

}