.NET Framework内置接口,构建自定义数据结构时的建议?

时间:2009-11-25 13:27:51

标签: c# .net data-structures interface

我在C#.NET 2.0中实现了一个AVL二叉树数据结构(可能会移到3.5)。我已经达到了通过初始单元测试而无需实现任何框架级接口的程度。

但是现在,只需查看FCL,我就会看到一大堆接口,包括非通用接口和通用接口,我可以实现这些接口以确保我的类与语言功能和其他数据结构完美匹配。

目前唯一明显的选择(至少对我来说)是Enumeration样式接口之一,允许调用者在foreach循环中使用树,以及稍后可能使用Linq。但是哪一个(或更多)?

以下是我目前正在考虑的界面:

  • IEnumerable和IEnumerable <T>
  • IEnumerator和IEnumerator <T>
  • IComparable和IComparable <T>
  • IComparer和IComparer <T>
  • ICollection和ICollection <T>
  • IEquatable和IEquatable <T>
  • IEqualityComparer和IEqualityComparer <T>
  • ICloneable
  • IConvertible

是否有任何已发布的指南,无论是在线还是书本形式,都提供了有关实施哪些框架接口以及何时实施的建议?

显然对于某些接口,如果您不想提供该功能,则不要实现整个接口。但似乎在FCL类中有某些约定(例如Collection类),在构建自定义数据结构时也许我们也应遵循这些约定。

理想情况下,建议会就何时使用IComparer或IEqualityComparer,IEnumerable或IEnumerator等问题提供指导?或者,如果您实现了通用接口,您是否还应该实现非基因接口?等等。

或者,如果您根据自己的经验提供指导,那将同样有用。

4 个答案:

答案 0 :(得分:2)

您应该知道其中一些接口相互继承(ICollection<T>IEnumberable<T>),并且接口的通用版本通常需要实现其非通用版本。 IEnumeratorIEnumerable已关联(IEnumerable传统上创建IEnumerator来进行枚举)

在集合上实现IComparable<T>充满了危险(你在比较集合中的成员吗?),IComparer<T>是排序方法的辅助界面。

ICloneable有点过时 - 但这意味着可以创建一个深层副本(同样,它也充满了收集的危险。

我对你的

有疑问
  

显然对于某些接口,如果您不想提供该功能,请不要实现它们。

如果实现了一个接口,则应该实现它的所有成员。 (见Liskov替代原则)

为集合实现IConvertible似乎也很奇怪 - 您可能更愿意实现ISerializable

接口的MSDN文档有点简洁,但您可以随时谷歌查看它们的工作方式。

答案 1 :(得分:1)

明确的指南是Framework Design Guidelines 它给出了Do,Do Not并考虑了建议。其中很多内容也可以在MSDN中找到。

答案 2 :(得分:1)

我认为你不会找到一个通用的答案,因为这些接口的实现取决于你对你的课程的使用方式。

提供所有这些接口是为了允许在现有BCL或语言本身中使用类。所以,正如你所说,IEnumerable允许在foreach循环中使用该类。

实现这些中的每一个取决于您的库的使用方式。例如,ICloneable直接适用于远程用户,有时也适用于ORM用户。如果您的课程在该环境中有意义,那么您将通过实施它来帮助您的用户。

换句话说:谁会使用你的课程?您希望他们使用哪些BCL框架方法?

(此外,许多通用接口本身实现非通用版本,例如IEnumerable实现IEnumerable,IEnumerator实现IEnumerator。)

答案 3 :(得分:0)

您只需实施您希望班级拥有的那些,即

  • 如果您希望能够枚举项目,请实施IEnumerableIEnumerable<T>,而不是发明自己的方法。
  • 如果您希望能够对树进行深层复制,请实施ICloneable,而不是发明自己的方法。
  • 如果您希望能够比较树的值相等,那么实现所有相等的接口。

等等。其他要点:

  • 某些接口应以特定方式实现,以避免在调用它们的代码中出现“令人惊讶”的行为。特别是等式接口必须彼此100%一致,并且System.Object虚拟等式方法。
  • 当存在同一接口的通用和非通用版本时,实现它们总是有用的。