比较两个复杂的列表对象

时间:2016-05-04 07:42:16

标签: c# linq

如何检查两个对象列表是否相同?我有列表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; }
}

我使用linq将其转换为列表。

列出A:

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

列表B:

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

这两个列表都不相同(remarkText字段)。我想要一段代码来比较这两个列表并返回相同或不同的代码。我怎么能这样做?

我尝试使用List1.Except(List2),但它没有比较。

修改

我创建了自定义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();
    }
}

并且

var Comparer = new Compare(); List1.Except(List2, Comparer)这应该有用吗?

修改

[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; }
}

2 个答案:

答案 0 :(得分:2)

首先修改test类并实现(覆盖)Equals函数。这将使您能够将自己与另一个对象进行比较,并判断它们是否相同。

理想情况下,每个类都应该有自己的Equals实现,而父类应该没有比较子对象内部的业务。但是看到你只需要比较你的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();
    }
}

然后,您可以轻松地轻松比较测试类的两个对象。

e.g。

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
}

答案 1 :(得分:0)

您的问题是内部类没有相等运算符重载==

例如,x.Details == y.Details始终返回false,无论实例持有哪些数据,因为默认的==运算符只调用Equals方法,这会导致引用相等,如在object.Equals方法中定义。

请参阅Guidelines for Overloading Equals() and Operator == (C# Programming Guide)

此外,GetHashCode方法中存在错误。永远不要使用字符串连接来计算哈希码。此外,您不会重载ToString方法,因此它只返回相同的默认字符串,这对于哈希码计算无用。