3

我有一个方法可以选择不同的对象集合,将它们添加到列表中,然后返回列表。

最初该方法返回 IEnumerable 但由于它返回一个不同的集合,我可以将不同的对象添加到一个哈希集中并返回 ISet 。

我很欣赏 ISet 使返回的对象可修改(消费者可以 Add() 到它),但无论如何我都会返回一个新列表,所以我认为这不会影响我,为什么我要关心消费者对集合做了什么一次他们有吗?

问题是,我应该这样做吗?或者我应该只返回 IEnumerable 并且很高兴它只包含不同的元素(目前由测试保证)

4

2 回答 2

2

与以往一样,对于设计,您在这里有相互矛盾的要求。优秀设计的艺术是为您正在创建的产品选择这些要求之间的最佳平衡。

界面设计的一个原则是您将界面视为合同或承诺。很明显,承诺或合同的规定性越低,就越容易遵守。因此,返回类型 ofIEnumerable<T>意味着您承诺只返回一系列事物。“更严格”或更多派生的类型将更具规范性,并且更难兑现承诺。

反思一下,如果您在函数中进行工作以确保返回类型更加衍生,那么通过返回较少说明性的父类型来放弃这项工作似乎是浪费。如果您已经有一个ISet<T>,定义一组事物,请明确,返回它并将调用者保存为不同检查的工作。

一般来说,没有简单的答案,正确的答案取决于调用者和您的系统。在一般情况下,我们不知道调用者。在没有证据的情况下,我们必须什么都不做,并从较弱的承诺中获得实实在在的好处。因此,总的来说,使用IEnumerable<T>它可以为您在未来提供更大的灵活性,而现在没有已知的成本。

在特定情况下,我们知道调用者将从集合的返回中受益。这是您在序列的独特性上引发错误的情况。显式并返回一个 是有意义的ISet<T>,这将有助于防止重复检查。需要注意的是,只有当每个可能的调用的数据都是不同的时,这才有意义。您必须确保您将信守对所有调用者的承诺,而不仅仅是那些提出错误的人。

于 2012-11-27T09:52:41.653 回答
0

在方法返回一系列唯一元素的情况下,为什么要查看您的问题的一个原因是“通过示例”返回类型应该是什么?

BCL 包括这样一种方法(您声明您正在使用),即Enumerable.Distinct<T>

该方法的返回类型是 IEnumerable。那么,为什么要使用一种不会自我投射实现将保持的所有承诺的类型呢?我可以看到两个论点

  • 从方法的名称和意图很明显
  • IEnumerable 契约更容易实现,比如 ISet,并且在大多数情况下会提供消费者需要的东西,并且在消费者可以创建 ISet 还不够的情况下。这就是为什么只有在获得价值时才需要成本的原因。

接口 IDistinctEnumerable 会改变这些吗?接口提供的唯一信息是名称。类型系统可以确保序列中的元素在运行时是唯一的,但因为它只是名称与我用于 Distinct 的参数本质上相同。如果从外部看,该方法期望返回一个集合,那么这很可能会永远保持下去,然后返回一个集合可能是值得的。然而,一系列独特的元素和一个集合之间是有区别的。

于 2012-11-27T11:13:45.170 回答