【问题标题】:Implementing IEquatable<T> where T is an interface实现 IEquatable<T> 其中 T 是一个接口
【发布时间】:2009-09-30 15:18:56
【问题描述】:

我有一个域模型,用以下内容简单地表示。

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 的潜在问题。乔恩的方法似乎是唯一简单的出路..
  • @nawfal:Jon 的方法是正确的,因为 IEqualityComparer&lt;T&gt; 代表相当广泛的等价形式是完全正常的,并且 T 可能对此一无所知。例如,碰巧实现IList&lt;T&gt; 的两个对象可能只报告自己彼此相等,如果它们总是以相同的顺序包含相同的项目。但是,如果一个对象能够将其拥有的列表存储到 Dictionary&lt;IList&lt;T&gt;,whaever&gt; 中,这可能很有用,其中包含任何序列中相同项目的列表将比较相同。
  • @nawfal:IList&lt;T&gt;中不存在这样的比较方法;实现通常也不提供一个。尽管如此,这种比较方法在某些情况下可能很有用,因此使用外部类以这种方式实现ICEqualityComparer&lt;IList&lt;T&gt;&gt; 是完全合理的。

标签: c# .net-3.5 class-design


【解决方案1】:

您可以在单独的类中实现IEqualityComparer&lt;T&gt;,而不是实现IEquatable&lt;T&gt;?在大多数情况下,如果您对相等性感兴趣,您可以指定一个比较器,我怀疑这样会更简洁。

【讨论】:

  • 这是个好主意,乔恩,感谢您的意见。我刚刚深入阅读了 C#,它教会了我很多关于我以前从未考虑过的语言的知识。我将立即阅读第二遍,以尝试将其全部吸收。
  • @Matthew:您可能想等到第二版出版后再读一遍 - 否则您需要读完 三遍 遍 :)
  • 您现在可以在 MEAP 上获得它 (manning.com/skeet2) - “新”章节基本完成;我现在正在修改旧的。应该会在 2010 年上半年的某个时候出纸版。
  • 太棒了,我得去看看。再次感谢关于 IEqualityComparer 的提示,效果很好。
【解决方案2】:

根据您的问题,您似乎知道 Equals 算法是什么,而且 ClassA 和 ClassB 的算法完全相同。为什么不这样做

  1. 定义 IMyInterface 继承自 IEquatable&lt;IMyInterface&gt;
  2. 定义一个抽象基类 MyInterfaceBase 实现 IMyInterface 并具有 IEquatable&lt;IMyInterface&gt; 实现
  3. 让 ClassA 和 ClassB 从 MyInterfaceBase 派生

【讨论】:

  • 我也考虑过这个,一直怕classA近期需要继承来实现其他目标,到时候我当然可以跨过那座桥,如果我我将沿着这条路线走,我不妨剪掉接口并使用抽象基类。也不是不可能的。感谢您的意见。
【解决方案3】:

如果IEquatable&lt;T&gt; 包含GetHashcode() 成员,则可以为该类型定义与Object.Equals 不同的有意义的语义(例如,“如果只查看T 中存在的特征,将对象被认为是相同的”)。但是,因为它没有,所以通常没有太多理由实现IEquatable&lt;T&gt;,除非它可以在不添加任何古怪语义的情况下提高性能。在实践中,这意味着IEquatable&lt;T&gt; 应该仅由T 本身实现(如果T 是密封类或结构),或者根本不实现(如果T 是可继承的,或者性能优势不是'不值得努力)。

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 2011-03-18
      • 1970-01-01
      相关资源
      最近更新 更多