IEquatable、IEqualityComparer和覆盖.Equals()之间的区别?在比较两个自定义对象集合时,我在使用Linq的.Except()方法时遇到了一些困难。我从Object派生了我的类,并实现了对Equals()、GetHashCode()和运算符==和!=的覆盖。我还创建了一个CompareTo()方法。在我的两个集合中,作为调试实验,我从每个列表(重复的)中取出第一项并像这样比较它们:itemListA[0].Equals(itemListB[0]);//真itemListA[0]==itemListB[0];//trueitemListA[0].CompareTo(itemListB[0]);//0在这三种情况下,结果都是我想要的。但是,当我使用Linq的Except()方法时,不会删除重复项:ListnewList=itemListA.Except(itemListB).ToList();了解Linq如何进行比较,我发现了各种(冲突?)方法,我们需要从IEquatable或IEqualityComparer等继承。我很困惑,因为当我从IEquatable继承时,我需要提供一个新的Equals()方法签名比我已经覆盖的签名。我是否需要两个具有不同签名的方法,或者我是否不再从Object派生我的类?我的对象定义(简化)如下所示:publicclassMyObject:Object{publicstringName{get;设置;}公共日期时间上次更新{get;set;}publicintCompareTo(MyObjectother){//...}publicoverrideboolEquals(objectobj){//允许对LastUpdate有一些容差}publicoverrideintGetHashCode(){unchecked{inthash=17;hash=hash*23+Name.GetHashCode();哈希=哈希*23+最后更新。获取哈希码();返回散列;}}//Overridesforoperators}我注意到当我从IEquatable继承时,我可以使用IEquatable或IEquatable;当我使用其中之一时,对Equals()签名的要求发生了变化。推荐的方法是什么?我想要实现的目标:我希望能够使用Linq(Distinct/Except)以及标准相等运算符(==和!=)而无需重复代码。如果两个对象具有相同的名称并且LastUpdate属性在秒数(用户指定)的公差范围内,则应允许它们相等。编辑:显示GetHashCode()代码。是否重写object.GetHashCode和object.GetHashCode,实现IEquatable还是为IEquatable提供IEqualityComparer。所有这些的工作方式都略有不同。1)OverrideEqualsandGetHashCodefromobject:从某种意义上说,这是基本情况。它通常会起作用,假设您能够编辑类型以确保这两种方法的实现符合需要。在很多情况下这样做并没有错。2)实施IEquatable这里的关键点是您可以(并且应该)实施IEquatable。这与#1之间的主要区别在于您拥有强大的Equals方法类型,而不是让它使用对象。这对程序员来说更方便(增加了类型安全性),也意味着不会对值类型进行装箱,因此这可以提高自定义结构的性能。如果这样做,除了#1之外,您应该始终执行此操作,而不是代替。这里的Equals方法在功能上与object.Equals不同,因为...哎呀。不要那样做。3)实现IEqualityComparer这与前两者完全不同。这里的想法是对象没有得到它自己的哈希码,或者看它是否等于其他东西。这种方法的症结在于对象不知道如何正确地获取它的散列,或者看看它是否等于其他东西。也许是因为您无法控制代码类型(即第3方库)并且他们没有费心覆盖行为,或者他们确实覆盖了它,但您只想要自己对“平等”的独特定义这个特定的上下文。在这种情况下,您将创建一个完全独立的“比较器”对象,它接受两个不同的对象并通知您它们是否相等,或者对象的哈希码是什么。使用此解决方案时,无论Equals或GetHashCode方法在类型本身中执行什么操作,您都不会使用它。请注意,所有这些都与==运算符完全无关,它本身就是野兽。您不能“允许对LastUpdate有一定的容忍度”,然后使用对LastUpdate使用严格值的GetHashCode()实现!假设this实例的LastUpdate时间为23:13:13.933,而obj实例的时间为23:13:13.932。那么这两个可能等于你的宽容想法。但如果是这样,它们的哈希码必须是相同的数字。但是,除非您非常幸运,否则这不会发生,因为DateTime.GetHashCode()不应该为您提供这两次相同的哈希值。此外,您的Equals方法在数学上主要是可传递的。而“约等于”是不能通过的。它的传递闭包是识别一切的平凡关系。我在对象中使用的基本模式如下。请注意,只有2个方法具有特定于对象的实际逻辑。剩下的只是提供这两种方法的样板代码}//这里实际的相等逻辑}publicoverrideintGetHashCode(){//这里实际的Hashcode逻辑}publicoverrideboolEquals(Objectobj){returnEquals(objasMyObject);}publicstaticbooloperator==(MyObjectleft,MyObjectright){if(Object.ReferenceEquals(left,null)){returnObject.ReferenceEquals(right,null);}返回left.Equals(right);}publicstaticbooloperator!=(MyObjectleft,MyObjectright){return!(left==right);如果您遵循此模式,则实际上不需要提供自定义IEqualityComparer。EqualityComparer.Default就足够了,因为它依赖于IEquatable来执行相等性检查以上是关于C#学习教程的全部内容:IEquatable、IEqualityComparer之间的区别以及在自定义对象集合上使用LINQ时覆盖.Equals()?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
