C# 列表如何<;T>;。除了比较项目?
因此,在比较两个不同的自定义对象列表的问题上,我得到了一个有趣的观察结果。我有一个overiden object.Equals()并有以下类:C# 列表如何<;T>;。除了比较项目?,c#,C#,因此,在比较两个不同的自定义对象列表的问题上,我得到了一个有趣的观察结果。我有一个overiden object.Equals()并有以下类: class Item { int ID; string Name; DayOfWeek[] days; public overide Equals(object obj) { if(obj.GetType == GetType() return this.Equals(ob
class Item
{
int ID;
string Name;
DayOfWeek[] days;
public overide Equals(object obj)
{
if(obj.GetType == GetType()
return this.Equals(obj)
return false;
}
public Equals(Item rhs)
{
if(this.ID == rhs.ID)
if(this.Name == rhs.Name)
if (this.days.OrderBy(i => i).SequenceEqual(rhs.days.OrderBy(i => i)))
return true;
return false;
}
}
使用以下代码时,我没有得到预期的结果:
List<Item> list1 = GetNewListFromDB();
List<Item> list2 = GetNewListFromDB();
//This is in a loop looking for changes to a table
//there is a delay between the list generation in the actual code
foreach(Item i in list1.Except(list2))
{
//DoStuff
}
在我对GetHashCode进行了过度编码之后,我得到了预期的结果。我一直在寻找,但找不到一个很好的解释列表。除了实际比较集合中的对象。我希望有人能向更新的程序员解释一下。
除了
之外,将第二个序列中的所有项放入一个基于哈希的集合,然后遍历第一个集合中的项,将每个项添加到集合中。此序列中添加时集合中不存在的任何项都将被生成
使用此基于哈希的集合意味着对象需要对
GetHashCode
和Equals
进行合理(一致)的定义(在对象本身上,或者通过另一个重载传递的IEqualityComparer
).除外
将第二个序列中的所有项目放入基于哈希的集合,然后遍历第一个集合中的项目,并将每个项目添加到集合中。此序列中添加时集合中不存在的任何项都将被生成
使用此基于哈希的集合意味着对象需要对
GetHashCode
和Equals
进行合理(一致)的定义(在对象本身上,或者通过另一个重载传递的IEqualityComparer
).它使用一个集合,该集合首先使用GetHashCode
:但也提到了它。始终实现/重写这两个函数,Equals
和GetHashCode
。Microsoft建议您在重写Equals
时重写GetHashCode
。这是MSDN上实现Equals页面指南的第一个要点EqualityComparer.Default
,它依次依赖于IEquatable.Equals
或重写object.Equals
和object.GetHashCode
。您的代码违反了Equals
的约定,因为它与GetHashCode
@CraigW不一致。注意:这不仅仅是一个建议——如果您重写Equals
,而不是GetHashCode
,编译器将发出警告。这就是为什么您从不忽略编译器警告的原因。:-)旁注:标题的正确答案应该是“列表。除了不比较项目,因为没有这样的方法”。。。请考虑为今后的问题提供有效的方法名称。请注意,文档明确指出,Except
通过比较器使用自定义对象的Equals
和GetHashCode
。它使用一个集合,该集合首先使用GetHashCode
:但也提到了它。始终实现/重写这两个函数,Equals
和GetHashCode
。Microsoft建议您在重写Equals
时重写GetHashCode
。这是MSDN上实现Equals页面指南的第一个要点EqualityComparer.Default
,它依次依赖于IEquatable.Equals
或重写object.Equals
和object.GetHashCode
。您的代码违反了Equals
的约定,因为它与GetHashCode
@CraigW不一致。注意:这不仅仅是一个建议——如果您重写Equals
,而不是GetHashCode
,编译器将发出警告。这就是为什么您从不忽略编译器警告的原因。:-)旁注:标题的正确答案应该是“列表。除了不比较项目,因为没有这样的方法”。。。请考虑为今后的问题提供有效的方法名称。请注意,文档明确指出,Except
通过比较器使用自定义对象的Equals
和GetHashCode
。这是@capnhector No的实现,它使用这两种操作,正如我在回答中明确指出的那样。@capnhector No,它同时使用这两种操作。如果不同时使用这两种方法,它就不在乎定义是否一致,它只需要一个合理的GetHashCode
实现。正如我在回答中特别指出的那样,这两种方法都需要有一个合理的定义。它需要这样做,因为它同时使用这两种方法。如果它不需要这两种操作,它就不需要对这两种操作都进行合理的定义。下面是@capnhector No的实现,它使用这两种操作,正如我在回答中明确指出的那样。@capnhector No,它同时使用这两种操作。如果不同时使用这两种方法,它就不在乎定义是否一致,它只需要一个合理的GetHashCode
实现。正如我在回答中特别指出的那样,这两种方法都需要有一个合理的定义。它需要这样做,因为它同时使用这两种方法。如果它不需要两者,它就不需要对两者进行合理的定义。
public overide GetHashCode()
{
int dayHashCode = 0;
foreach(DayOfWeek d in days)
{
dayHashCode = dayHashCode ^ d.GetHashCode();
}
return this.ID.GetHashCode() ^ this.Name.GetHashCode() ^ dayHashCode
}