问题描述
如何检查两个对象列表是否相同?我的列表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
在这里,两个列表都不相同(备注字段).我想要一个代码,该代码将比较这两个列表并返回相同的代码.我该怎么做?
我尝试使用List1.Except(List2),但没有比较.
编辑
我创建了Custom 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; } }
推荐答案
首先修改您的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(); } }
然后,您可以轻松地比较测试类的两个对象.
例如
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 }
其他推荐答案
您的问题是内部类没有平等操作员超载==.
例如,x.Details == y.Details始终返回false,无论该实例存在哪个数据,因为默认==运算符只是调用equals方法,该方法会导致参考平等,如object.Equals方法所定义.
请参阅 for equals()和操作员的指南==(C#编程指南)
另外,GethashCode方法中也存在错误.切勿使用字符串串联计算哈希码.另外,您的ToString方法不超载,因此它只是返回相同的默认字符串,该字符串对于哈希代码计算无用.
问题描述
How to check if two list of objects are same? I have list A and list B with same structure:
[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.
List 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). 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.
Edit
I have created custom 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) Should this work?
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. 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. But seeing that you need to compare only your test class, we implement all the comparison logic in the test class itself.
[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.
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 }
其他推荐答案
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.
See Guidelines for Overloading Equals() and Operator == (C# Programming Guide)
Also, there is an error in GetHashCode method. 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.