答案 0 :(得分:12)
IEnumberable<T>
是只读的,您必须重新构建集合才能对其进行更改。另一方面,IList<T>
是可读写的。因此,如果您希望对集合进行大量更改,请公开IList<T>
,但如果可以安全地假设您不会对其进行修改,请使用IEnumerable<T>
。
答案 1 :(得分:7)
始终使用提供所需功能的最严格的界面,因为这为您提供了以后更改实施的最大灵活性。因此,如果IEnumerable<T>
已足够,则使用该...如果您需要列表功能,请使用IList<T>
。
最好使用强类型通用版本。
答案 2 :(得分:4)
我遵循的原则是我读过一段时间的原则:
“消费最简单,并揭露 最复杂的“
(我确定这是非常常见的,我误报了它,如果有人知道你的来源,你可以发表评论或编辑吗......)
(编辑补充 - 嗯,这里我几周后,我刚刚在一个完全不同的背景下遇到这个引用,它看起来像是Robustness Principle或Postel定律 - < / p>
保守你所做的事;在你接受别人的事上要自由。
最初的定义是通过互联网进行网络通信,但我确信我已经看到它用于在OO中定义类合同。)
基本上,如果你要定义一个外部消费方法,那么参数应该是最基本的类型,为你提供所需的功能 - 在你的例子中,这可能意味着接受IEnumerable而不是IList。这为客户端代码提供了最大的灵活性。另一方面,如果您要公开一个属性以供外部使用,那么使用最复杂的类型(IList或ICollection而不是IEnumerable)这样做,因为这样可以为客户端提供最多的代码。他们使用对象的方式具有灵活性。
我发现自己和Dr.Jokepu之间的谈话很有吸引力,但我也很欣赏这不应该是一个讨论论坛,所以我会编辑我的答案,进一步概述我选择降压背后的原因趋势并建议您将其暴露为IList(实际上,正如您所见,列表)。让我们说这是我们正在讨论的课程:
public class Example
{
private List<int> _internal = new List<int>();
public /*To be decided*/ External
{
get { return _internal; }
}
}
首先,让我们假设我们将External暴露为IEnumerable。我在其他答案和评论中看到的原因目前是:
虽然IEnumerable只公开只读功能,但不会使它只读。您返回的实际类型很容易通过反射或简单地暂停调试器并查找,因此将其强制转换回List&lt;&gt;,这同样适用于下面注释中的FileStream示例。如果你试图保护这个成员,那么假装它就不是其他方法了。
我不相信这是事实上的标准。我在.NET 3.5库中找不到任何代码,Microsoft可以选择返回具体集合并返回接口。由于LINQ,IEnumerable 在中更常见,但这是因为它们不能公开更多派生类型,而不是因为它们不想这样做。
现在,减少我同意的耦合 - 一点 - 基本上这个论点似乎是你告诉客户端,当你返回的对象是我希望你对待的列表是一个IEnumerable,以防您决定稍后更改内部代码。忽略这个问题以及无论如何真实类型暴露的事实它仍然留下“为什么停止IEnumerable?”的问题。如果您将其作为对象类型返回,那么您将完全自由地将实现更改为任何内容!这意味着您必须已决定客户端代码需要多少功能,因此您要么编写客户端代码,要么基于任意指标做出决策。
最后,如前所述,您可以假设实现细节始终在.NET中公开,特别是如果您公开公开该对象。
所以,在那么长的dia骂之后还剩下一个问题 - 为什么要把它作为List&lt;&gt;?好吧,为什么不呢?你没有通过将它暴露为IEnumerable获得任何东西,那么为什么人为地限制客户端代码使用该对象的能力呢?想象一下,如果Microsoft已经确定Winforms控件的Controls集合应该显示为IEnumerable而不是ControlCollection - 您将无法再将其传递给需要IList的方法,处理任意索引的项目,或查看是否包含一个特定的控件,除非你施放它。微软实际上并没有获得任何收益,这只会给你带来不便。
答案 3 :(得分:3)
当我只需要枚举孩子时,我使用IEnumerable。如果我碰巧需要Count,我会使用ICollection。不过,我试图避免这种情况,因为它暴露了实现细节。
答案 4 :(得分:2)
IList<T>
确实是一个非常强大的界面。我更喜欢公开Collection<T>
- 派生类型。这与Jeffrey Richter建议做的几乎一致(附近没有书,所以不能指定页/章号):方法应该接受最常见的类型作为参数,并返回最“派生”的类型作为返回值。
答案 5 :(得分:1)
如果通过属性公开只读集合,那么传统的方法是将它公开为ReadOnlyCollection(或派生类),包装你拥有的任何东西。它向客户端公开了IList的全部功能,但它非常清楚它是只读的。