修改
我要做的是找出db.Id
是否等于xml.Id
而db.SubTitle
等于xml.SubTitle
....等等.... .all my prop
我也尝试了
bool result = db.SequenceEqual(xml)
它始终返回false。
ENd EDIT
在我最终寻求帮助之前,我确实进行了搜索,但我不确定解决问题的最佳方法是什么。
我有两个IList对象,两者都具有完全相同的属性,但数据可能不同。 一个对象从db填充,其他对象从xml读取以比较两个源是同步的。
这是我的对象看起来像:
public class EmployeeObject
{
public Int32 Id { get; set; }
public string SubTitle { get; set; }
public string Desc { get; set; }
public bool Active { get; set; }
public string ActiveDateTime { get; set; }
}
这是我尝试过的:
IList<EmployeeObject> db = Db.EmployeeRepository.PopulateFromDb();
IList<EmployeeObject> xml = Xml.EmployeeRepository.PopulateFromXml();
//到目前为止,这两个对象都填充了数据......
现在比较的时间:
我尝试过这样的事情:
if ((object)xml == null || ((object)db) == null)
return Object.Equals(xml, db);
return xml.Equals(db); // returning false all the time
我检查过两个对象都有完全相同的数据,但仍然返回false
答案 0 :(得分:5)
您正在使用的Equals
方法将确定两个引用是否引用相同的列表,而不是内容是否相同。您可以使用SequenceEqual
来实际验证两个序列具有相同顺序的相同项目。
接下来,您将遇到这样的问题:列表中的每个项目都将进行比较,以查看它们是否引用相同的对象,而不是包含相同的字段值或相同的ID值,如同似乎是什么你想要的。一个选项是自定义比较器,但另一个选项是拉出有问题的“身份”对象:
bool areEqual = db.Select(item => item.id)
.SequenceEqual(xml.Select(item => item.id));
答案 1 :(得分:3)
您应该覆盖类中的Equals
和GetHashCode
,如下所示:
public class EmployeeObject {
public Int32 Id { get; set; }
public string SubTitle { get; set; }
public string Desc { get; set; }
public bool Active { get; set; }
public string ActiveDateTime { get; set; }
public override bool Equals(object o){
EmployeeObject e = o as EmployeeObject;
if(e == null) return false;
return Id == e.Id && SubTitle == e.SubTitle && Desc == e.Desc
&& Active == e.Active && ActiveDateTime == e.ActiveDateTime;
}
public override int GetHashCode(){
return Id.GetHashCode() ^ SubTitle.GetHashCode() ^ Desc.GetHashCode()
^ Active.GetHashCode() ^ ActiveDateTime.GetHashCode();
}
}
然后使用SequenceEqual
方法:
return db.OrderBy(e=>e.Id).SequenceEqual(xml.OrderBy(e=>e.Id));
答案 2 :(得分:1)
IList
没有Equals
方法。您调用的是标准Object equals,它检查两个变量是否指向同一个对象。
如果要检查列表是否在语义上等效,则需要检查列表中的每个对象是否相同。如果EmployeeObject
类具有适当的Equals
方法,则可以使用SequenceEquals
来比较列表。
答案 3 :(得分:1)
您可以实施IEqualityComparer并使用the overload of SequenceEquals that takes an IEqualityComparer。以下是来自msdn的IEqualityComparer的示例代码:
class BoxEqualityComparer : IEqualityComparer<Box>
{
public bool Equals(Box b1, Box b2)
{
if (b1.Height == b2.Height && b1.Length == b2.Length && b1.Width == b2.Width)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(Box bx)
{
int hCode = bx.Height ^ bx.Length ^ bx.Width;
return hCode.GetHashCode();
}
}
然后你可以使用这样的SequenceEquals:
if (db.SequnceEquals(xml), new MyEqualityComparer())
{ /* Logic here */ }
请注意,如果项目也按列表中的相同顺序排序,则此选项仅返回true。如果合适,您可以预先订购这样的项目:
if (db.OrderBy(item => item.id).SequnceEquals(xml.OrderBy(item => item.id)), new MyEqualityComparer())
{ /* Logic here */ }
答案 4 :(得分:0)
显然,如果您要比较两个不同的列表,return xml.Equals(db);
的返回将始终为false
。
理解这一点的唯一方法是让你真正更具体地了解这两个列表相等的含义。那就是你需要浏览两个列表中的元素,并确保列表都包含相同的项。即使这是不明确的,但假设您的元素为Equals()
和GetHashCode()
提供了适当的覆盖,那么您可以继续实现该实际的列表比较。
通常,比较两个不包含重复项的列表的最有效方法是使用从其中一个列表的元素构造的哈希集,然后遍历第二个元素的元素,测试是否找到每个元素在哈希集中。
如果列表包含重复项,那么最好的选择是对它们进行排序,然后串联列表,确保每个点的元素匹配。
答案 5 :(得分:0)
如果您可以实际比较SequenceEqual
的实例,则可以使用EmployeeObject
。您可能必须Equals
上的EmployeeObject
:
public override bool Equals(object o)
{
EmployeeObject obj = o as EmployeeObject;
if(obj == null) return false;
// Return true if all the properties match
return (Id == obj.Id &&
SubTitle == obj.SubTitle &&
Desc == obj.Desc &&
Active == obj.Active &&
ActiveDateTime == obj.ActiveDateTime);
}
然后你可以这样做:
var same = db.SequenceEqual(xml);
您还可以传入一个实现IEqualityComparer
的类,该类指示SequenceEqual
如何比较每个实例:
var same = db.SequenceEqual(xml, someComparer);
另一种快速的方法,虽然不是那么快,但是要构建两个你想要比较的值的枚举,可能是你案例中的id
属性:
var ids1 = db.Select(i => i.Id); // List of all Ids in db
var ids2 = xml.Select(i => i.Id); // List of all Ids in xml
var same = ids1.SequenceEqual(ids2); // Both lists are the same