为什么返回一个集合接口而不是具体类型?

20

我注意到在其他人的代码中,返回通用集合的方法几乎总是返回一个接口(例如 IEnumerable<T>IList<T>),而不是具体实现。

我的两个相关问题。首先,为什么(如果有的话)被认为返回接口更好?其次,是否有一种包含 Sort 方法的集合接口(如 List<T>)?

4个回答

26

关于第一个问题:如果你返回一个接口,你将获得更多的灵活性。稍后你可以更改实现以返回不同的具体类型。然而,显然会给调用者提供较少的信息,因此他们可能无法执行某些操作。(例如,如果你返回 List<T>,则调用者可以使用ConvertAll等方法...但如果你只声明返回类型为IList<T>,则不能这样做)。在一些情况下,指定具体类型是值得的;我通常倾向于从接口开始,只有当发现经常需要使用额外的可用方法时才将具体类型作为返回类型。

其次,没有标准集合接口具有Sort方法。另一方面,你可以编写扩展方法来对任何IList<T>进行排序。个人而言,我通常更喜欢使用LINQ的OrderByOrderByDescendingThenByThenByDescending方法……虽然它们返回一个新序列,而不是在原地排序。


2
太棒了!感谢您对我的问题给出清晰的答案。 - David

7

来自C# - List or IList

如果你要通过一个库让别人使用你的类,一般来说你应该通过接口而不是具体实现来暴露它。这样做可以帮助你,如果你决定以后更改你的类的实现方式使用不同的具体类,那么使用你的库的用户就不需要更新他们的代码,因为接口没有变化。

如果你只是在内部使用它,可能不太关心这个问题,使用List可能没问题。


谢谢你,非常有帮助。但问题是,我不是在为外部编写库,而是为一家公司编写内部网站,而我是唯一的开发人员。这可能会让我难以理解某些事情的目的。 - David
是的,如果它是纯内部使用的,并且您确信它不会暴露给公众或软件的多个部分,那么返回一个List<T>对象应该是可以的。但是,例如,如果它是一个类库,虽然现在仅用于您的应用程序,但您可能希望扩展您的应用程序并再次使用该库,因此您将受到List<T>的限制而不是您自己的实现。 - Michal Ciechan

2
我们使用接口来增加实现的灵活性。因此,如果您的方法具有IEnumerable的返回类型,您可以将其返回的对象从List更改为Array,而不会改变依赖于该方法的对象。
它还很表达:如果您返回一个IEnumerable,当使用对象时,编码器清楚地知道我们只关心它是某种集合,而不是特定类型。

1

我不能代表每个人,但通常我这样做只是因为我喜欢只返回我需要的内容。当你只需要一个可枚举的集合时,为什么要返回一个完整的集合呢?

至于你问题的另一部分,你可以始终使用IList,然后使用LINQ进行排序:

list.OrderBy(a=>a.Id);

谢谢,我现在明白了。我不知道我有OrderBy可用,因为它是一个扩展方法,而且我没有使用命名空间。 - David
太好了。是的,LINQ的扩展方法非常棒。 - spinon
@spinon:当然,我会评论我的反对票:同样地,作为调用方,我更愿意获得最具体的集合类型。如果代码返回一个List<T>,那么我可以直接使用它,或者作为IList<T>IEnumerable<T>等等。这给调用方提供了更多选择。但这不是真正的问题所在。它是为了防止方法实现的更改破坏调用代码。如果该方法返回一个IEnumerable<T>,那么我可以更改实现以使用任何支持该接口的容器,而无需修改调用代码。 - Mhmmd
@ShaderOp 我不明白。集合是基于集合中的类型而具体的,而不是包含项的类型。包含项只是确定可用功能的方式。但是,如果需要更多功能,您可以根据 ilist 创建一个新列表。我不认为我理解您的论点,因为我无法弄清楚您是否在说好坏。感谢您的回复。很有兴趣知道思考的过程。 - spinon
3
我认为你提出的推理是错误的。这并不仅仅是关于调用代码获取其所需内容的问题,因为--正如我所说--给调用代码更多选项并让它自行选择同样有道理。正如已经说明的那样,而实际上更喜欢返回一个 IEnumerable 而不是一个具体的 List 的真正原因是为了保护调用代码免受实现变化的影响。抱歉,但我认为这个区别非常重要。 - Mhmmd
@ShaderOp 不需要为投反对票道歉。如果您感觉如此,那就是您的感觉。我只是好奇为什么会有反对票,因为我的回答似乎与其他人说的一样。请注意所选答案第一段中的最后一句话。该用户提到了类似的想法。只返回实际需要的最小内容。如果您发现需要更多选项,则可以返回更多。不管怎样,感谢您给出的理由。 - spinon

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