简体   繁体   English

比较两个复杂的列表对象

[英]Compare two complex list objects

How to check if two list of objects are same?如何检查两个对象列表是否相同? I have list A and list B with same structure:我有列表 A 和列表 B 具有相同的结构:

[XmlRoot(ElementName = "Details")]
public class Details
{
    [XmlElement(ElementName = "time")]
    public string time { get; set; }
    [XmlElement(ElementName = "duration")]
    public string duration { get; set; }
}

[XmlRoot(ElementName = "Remark")]
public class Remark
{
    [XmlElement(ElementName = "RemarkText")]
    public string RemarkText { get; set; }
    [XmlElement(ElementName = "isRemarkVisible")]
    public Boolean IsRemarkVisible { get; set; }
}

[XmlRoot(ElementName = "test")]
public class test
{
    [XmlElement(ElementName = "ID")]
    public string ID { get; set; }
    [XmlElement(ElementName = "Name")]
    public string Name { get; set; }
    public Details Details { get; set; }
    [XmlElement(ElementName = "Remark")]
    public Remark Remark { get; set; }
}

[XmlRoot(ElementName = "Tests")]
public class Tests
{
    [XmlElement(ElementName = "test")]
    public test[] test { get; set; }
}

I convert it to list using linq.我使用 linq 将其转换为列表。

List A:清单 A:

Test
id=1
name=abc
details
    starttime=9.00
    endtime=12.00
    duration=1hr
Remark
    RemarkText= remark1 
    IsRemarkVisible=true

List B:名单乙:

Test
id=1
name=abc
details
    starttime=9.00
    endtime=12.00
    duration=1hr
Remark
    RemarkText= remark2 
    IsRemarkVisible=true

Here both the lists are not same(remarkText field).这里两个列表都不相同(remarkText 字段)。 I want a piece of code which will compare these two list and return whether same or no.我想要一段代码来比较这两个列表并返回是否相同。 How can i do that?我怎样才能做到这一点?

I tried using List1.Except(List2) but it doesn't compare.我尝试使用List1.Except(List2)但它没有比较。

Edit编辑

I have created custom IEqualityComparer:我创建了自定义 IEqualityComparer:

public class Compare : IEqualityComparer<test>
{
    public bool Equals(test x, test y)
    {
        if (x == null || y == null) return false;

        bool equals = x.ID == y.ID && x.Name == y.Name && x.Remark == y.Remark
            && x.Details == y.Details;
        return equals;
    }
    public int GetHashCode(test codeh)
    {
        return (codeh.ID + codeh.Name + codeh.Remark + codeh.Details).GetHashCode();
    }
}

And

var Comparer = new Compare(); List1.Except(List2, Comparer) var Comparer = new Compare(); List1.Except(List2, Comparer) Should this work? var Comparer = new Compare(); List1.Except(List2, Comparer)这应该有效吗?

Edit编辑

[XmlRoot(ElementName = "Details")]
public class Details
{
    [XmlElement(ElementName = "starttime")]
    public string starttime { get; set; }
    [XmlElement(ElementName = "endtime")]
    public string endtime { get; set; }
    [XmlElement(ElementName = "duration")]
    public string duration { get; set; }
}

[XmlRoot(ElementName = "Remark")]
public class Remark
{
    [XmlElement(ElementName = "RemarkText")]
    public string RemarkText { get; set; }
    [XmlElement(ElementName = "isRemarkVisible")]
    public Boolean IsRemarkVisible { get; set; }
}

[XmlRoot(ElementName = "test")]
public class test
{
    [XmlElement(ElementName = "ID")]
    public string ID { get; set; }
    [XmlElement(ElementName = "Name")]
    public string Name { get; set; }
    public Details Details { get; set; }
    [XmlElement(ElementName = "Remark")]
    public Remark Remark { get; set; }
    [XmlElement(ElementName = "Tags")]
    public Tags Tags { get; set; }
}

[XmlRoot(ElementName = "Tags")]
public class Tags
{
    [XmlElement(ElementName = "TagLocation")]
    public TagLocation[] TagLocation { get; set; }
}

[XmlRoot(ElementName = "TagLocation")]
public class TagLocation
{
    [XmlElement(ElementName = "Id")]
    public string Id { get; set; }
    [XmlElement(ElementName = "TagText")]
    public string TagText { get; set; }
}

[XmlRoot(ElementName = "Tests")]
public class Tests
{
    [XmlElement(ElementName = "test")]
    public test[] test { get; set; }
}

First modify your test class and implement (override) the Equals function.首先修改您的test类并实现(覆盖) Equals函数。 This will give you class the ability to compare itself with another object and tell whether both are same or not.这将使您能够将自己与另一个对象进行比较并判断两者是否相同。

Ideally, each of your class should have its own Equals implementation, and the parent class should have no business of comparing the internals of child objects.理想情况下,您的每个类都应该有自己的Equals实现,并且父类不应该比较子对象的内部结构。 But seeing that you need to compare only your test class, we implement all the comparison logic in the test class itself.但是看到您只需要比较您的test类,我们在test类本身中实现了所有比较逻辑。

[XmlRoot(ElementName = "test")]
public class test
{
    [XmlElement(ElementName = "ID")]
    public string ID { get; set; }
    [XmlElement(ElementName = "Name")]
    public string Name { get; set; }
    public Details Details { get; set; }
    [XmlElement(ElementName = "Remark")]
    public Remark Remark { get; set; }
    [XmlElement(ElementName = "Tags")]
    public Tags Tags { get; set; }

    // override object.Equals
    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType()) return false;

        // modify the code below to suit your needs...
        test objA = (test)obj;
        if (
                this.ID != objA.ID || this.Name != objA.Name
                || this.Details.duration != objA.Details.duration || this.Details.starttime != objA.Details.starttime || this.Details.endtime != objA.Details.endtime
                || this.Remark.IsRemarkVisible != objA.Remark.IsRemarkVisible || this.Remark.RemarkText != objA.Remark.RemarkText
            ) return false;
        if (this.Tags.TagLocation.Length != objA.Tags.TagLocation.Length) return false;
        for (int i = 0; i < this.Tags.TagLocation.Length; i++)
        {
            if (this.Tags.TagLocation[i].Id != objA.Tags.TagLocation[i].Id || this.Tags.TagLocation[i].TagText != objA.Tags.TagLocation[i].TagText) return false;
        }
        return true;    // if everything matched we infer that the objects are equal.
    }

    // override object.GetHashCode
    public override int GetHashCode()
    {
        // modify the code below to generate a unique hash code for your object.
        return base.GetHashCode();
    }
}

Then you can easily compare two objects of your test class easily.然后,您可以轻松地比较测试类的两个对象。

eg例如

private void button1_Click(object sender, EventArgs e)
{

    test test1, test2, test3;

    test1 = new test { ID="1", Name ="abc"};
    test1.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" };
    test1.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark1" };
    test1.Tags = new Tags();
    test1.Tags.TagLocation = new TagLocation[] 
    { 
         new TagLocation{ Id = "1", TagText = "tag1" },
         new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    test2 = new test { ID = "1", Name = "abc" };
    test2.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" };
    test2.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark2" };
    test2.Tags = new Tags();
    test2.Tags.TagLocation = new TagLocation[] 
    { 
         new TagLocation{ Id = "1", TagText = "tag1" },
         new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    test3 = new test { ID = "1", Name = "abc" };
    test3.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" };
    test3.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark2" };
    test3.Tags = new Tags();
    test3.Tags.TagLocation = new TagLocation[] 
    { 
         new TagLocation{ Id = "1", TagText = "tag1" },
         new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    MessageBox.Show("test1.Equals(test2) ... " + test1.Equals(test2).ToString());   // shows false
    MessageBox.Show("test2.Equals(test3) ... " + test2.Equals(test3).ToString());   // shows true
}

Your problem is that the inner classes do not have equality operator overloads == .您的问题是内部类没有相等运算符重载==

For example, x.Details == y.Details always returns false , no matter which data the instances hold, because the default == operator just calls the Equals method, which results in a reference equality, as defined in object.Equals method.例如, x.Details == y.Details始终返回false ,无论实例保存哪些数据,因为默认==运算符只调用 Equals 方法,这会导致引用相等,如object.Equals方法中所定义。

SeeGuidelines for Overloading Equals() and Operator == (C# Programming Guide)请参阅重载 Equals() 和 Operator == 指南(C# 编程指南)

Also, there is an error in GetHashCode method.此外,GetHashCode 方法中存在错误。 Never compute the hash codes with string concatenation.永远不要用字符串连接来计算哈希码。 In addition, your don't overload the ToString method, so it just returns the same default string which is not useful for hash code computation.此外,您不要重载ToString方法,因此它只返回相同的默认字符串,这对哈希码计算没有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM