4

我最近在别处*表达了我对此的看法,但我认为它值得进一步分析,所以我将其作为自己的问题发布。

假设我需要在我的程序中创建和传递一个容器。至少在现阶段,我可能对一种容器与另一种容器没有强烈的看法,但我确实选择了一个;为了争论,假设我将使用List<>

问题是:编写我的方法来接受和返回高级接口(例如 C# 的IEnumerable )是否更好?或者我应该编写方法来获取和传递我选择的特定容器类。

我应该寻找哪些因素和标准来决定?哪种程序可以从其中一种或另一种中受益?计算机语言会影响您的决定吗?表现?程序规模?个人风格?

(这还重要吗?)

**(作业:找到它。但请在寻找我自己的答案之前在这里发布您的答案,以免偏见您。)*

4

6 回答 6

16

您的方法应始终接受执行其功能所需的最不具体的类型。如果您的方法需要枚举,请接受IEnumerable. 如果它需要做IList<>特定的事情,根据定义,你必须给它一个IList<>.

于 2009-03-05T05:24:33.757 回答
5

唯一会影响您的决定的是您计划如何使用该参数。如果您只是对其进行迭代,请使用IEnumerable<T>. 如果您正在访问索引成员(例如var x = list[3])或以任何方式修改列表(例如list.Add(x)),请使用ICollection<T>IList<T>

于 2009-03-05T05:24:22.307 回答
3

正是与我的讨论引发了这个问题,所以 Euro Micelli 已经知道我的答案了,但就是这样!:)

我认为 Linq to Objects 已经为这个问题提供了一个很好的答案。通过对一系列项目使用最简单的接口,它为如何实现该序列提供了最大的灵活性,这允许延迟生成,在不牺牲性能的情况下提高生产力(不是真正意义上的)。

确实,过早的抽象会产生成本——但主要是发现/发明新抽象的成本。但是,如果您已经为您提供了非常好的接口,那么如果您不利用它们,那就太疯狂了,而这正是通用集合接口为您提供的。

有些人会告诉你,公开一个类中的所有数据“更容易”,以防万一你需要访问它。同样,Euro 建议最好对容器IList<T>(甚至是具体的类List<T>)使用丰富的接口,然后再清理这些烂摊子。

但我认为,就像最好隐藏一个你不想访问的类的数据成员一样,让你以后可以轻松地修改该类的实现,所以你应该使用最简单的接口来引用一系列项目。在实践中,先暴露一些简单和基本的东西,然后再“放松”它,这比从松散的东西开始并努力强加秩序要容易得多。

所以假设IEnumerable<T>会代表一个序列。然后在您需要AddRemove项目(但仍不需要按索引查找)的情况下,使用IContainer<T>继承IEnumerable<T>,因此将与您的其他代码完美互操作。

这样一来(仅通过对某些代码的本地检查)就可以完全清楚地知道该代码将能够对数据做什么。

小程序需要较少的抽象,这是真的。但如果他们成功了,他们往往会成为大项目。如果他们首先使用简单的抽象,这会容易得多。

于 2009-03-05T09:39:59.430 回答
3

总是有一个权衡。一般的经验法则是在层次结构中尽可能高地声明事物。因此,如果您只需要访问 IEnumerable 中的方法,那么这就是您应该使用的。

另一个最近的 SO 问题示例是一个 C API,它采用文件名而不是 File *(或文件描述符)。那里的文件名严重限制了可以传递的东西(有很多东西可以用文件描述符传递,但只有一个有文件名)。

一旦你必须开始铸造,你要么太高了,要么你应该制作第二种方法,采用更具体的类型。

我能想到的唯一例外是当速度是绝对必要的并且您不想花费虚拟方法调用的费用时。声明特定类型消除了虚函数的开销(将取决于语言/环境/实现,但作为可能正确的一般陈述)。

于 2009-03-05T05:47:00.520 回答
0

我在这里回答了一个类似的 C# 问题。我认为您应该始终提供最简单的合同,在我看来,在集合的情况下,通常是 IEnumerable Of T。

该实现可以由内部 BCL 类型提供 - 无论是 Set、Collection、List 等 - 其所需成员由您的类型公开。

您的抽象类型始终可以继承简单的 BCL 类型,这些类型由您的具体类型实现。在我看来,这可以让你更容易地坚持LSP

于 2009-03-05T09:21:20.740 回答
0

这确实很重要,但正确的解决方案完全取决于使用情况。如果您只需要做一个简单的枚举,那么一定要使用 IEnumerable,这样您就可以传递任何实现者来访问您需要的功能。但是,如果您需要列表功能,并且您不想创建列表的新实例,如果碰巧每次调用该方法时传递的可枚举不是列表,那么请使用列表。

于 2009-03-05T05:26:20.537 回答