实现IEquatable<T>,其中T是一个接口。

8
我有一个域模型,可以用以下简单表示。
IMyInterface

ClassA : IMyInterface

ClassB : IMyInterface

我希望你能实现IEquatable的功能,使我能够编写类似以下代码的内容。
if(dynamicallyCreatedInstanceOfClassA == dynamicallyCreatedinstanceOfClassB)
{
  // Do something relevant
}

我的第一反应是让IMyInterface实现IEquatable,但当然我不能在IMyInterface中实现。我必须在ClassA和ClassB中实现。这种解决方案的问题在于,ClassA和ClassB中IEquatable的实现将完全相同,一行一行地相同。有没有一种优雅的方法来完成这个任务?当ClassC出现时,我不想复制和粘贴50行重复的IEquatable代码。
我考虑使用抽象基类代替接口,但在这种情况下,IMyInterface只描述了类将执行的操作,而不是类本身。ClassA和ClassB除了都能执行IMyInterface合同中的操作之外,并没有太多相似之处。
任何见解都是有帮助的,感谢您的时间。

我也会建议采用抽象方式,但缺点是这将限制您的派生类从另一个具体类继承,因为C#不允许MI。请参阅supercat的答案以了解涉及“GetHashCode”的潜在问题。看来Jon的方法是唯一的简单出路。 - nawfal
1
@nawfal:Jon的方法是正确的,因为IEqualityComparer<T>通常代表着广泛的等价形式,而T可能对此一无所知。例如,两个恰好实现了IList<T>的对象,只有当它们始终包含相同顺序的相同项时,才应该报告它们彼此相等。然而,一个对象能够将其拥有的列表存储到Dictionary<IList<T>,whaever>中可能很有用,其中包含任何顺序相同的项的列表将比较相同。 - supercat
1
@nawfal:IList<T>中不存在这样的比较方法;实现通常也不会提供这样的方法。尽管如此,在某些情况下,这样的比较方法可能是有用的,因此使用外部类来实现一个以这种方式实现的ICEqualityComparer<IList<T>>是完全合理的。 - supercat
4个回答

8

与其实现IEquatable<T>,你可以在一个单独的类中实现IEqualityComparer<T>吗?在大多数情况下,当你关心相等性时,你可以指定一个比较器,我认为这样会更清晰。


那是个好主意Jon,感谢你的建议。我已经差不多读完了《深入理解C#》,它教会了我很多关于这门语言以前从未考虑过的东西。我将立即第二次阅读它,以尽可能吸收所有知识。 - Matthew Vines
@Matthew:你可能想等第二版出来再重新读一遍——否则你需要读三遍 :) - Jon Skeet
现在您可以在MEAP上获取它(http://manning.com/skeet2)-“新”的章节基本上已经完成;我现在正在修订旧的章节。预计将在2010年上半年以实体书形式出版。 - Jon Skeet
太棒了,我得去看看。再次感谢你关于IEqualityComparer<T>的提示,它非常好用。 - Matthew Vines

5

根据您的问题,似乎您知道Equals算法将是什么,并且对于ClassA和ClassB来说它们完全相同。为什么不这样做:

  1. 定义IMyInterface从IEquatable<IMyInterface>继承
  2. 定义抽象基类MyInterfaceBase,该类实现IMyInterface并拥有IEquatable<IMyInterface>实现
  3. 让ClassA和ClassB从MyInterfaceBase派生

我也考虑过这个问题,但我担心ClassA在不久的将来需要继承以实现其他目标,当然,如果我到达那里,我可以解决这个问题。如果我要走这条路,我可能会直接取消接口并使用抽象基类,这也不是不可能。感谢您的意见。 - Matthew Vines

1
如果IEquatable<T>包含一个GetHashcode()成员,可能会定义有意义的语义,该语义与Object.Equals不同(例如,“如果只看T中存在的特征,对象是否被认为相同”)。然而,由于它没有,因此通常没有太多理由实现IEquatable<T>,除非在那些可以提高性能而不添加任何古怪语义的情况下。在实践中,这意味着IEquatable<T>应该仅由T本身实现(如果T是封闭类或结构),或者根本不实现(如果T是可继承的,或者性能收益不值得努力)。

0
我认为,如果接口无法转换为抽象类,则直接或自动地比较这两个实现类之间并没有太多意义。这意味着在每个类上实现自定义比较将是正确的方法。我相信你可以以某种方式重构比较代码,以便稍后更轻松地进行更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接