Why is it considered bad to expose List<T>?
根据fxcop,列表不应该在API对象模型中公开。为什么这被认为是不好的做法?
- 我在2008年12月23日问了这个问题。您链接的问题已于2008年12月30日发布。我会说我的先来。
我同意这里丛林中的驼鹿:List是一个不受约束的、膨胀的物体,里面有很多"行李"。
幸运的是,解决方案很简单:改为公开IList。
它公开了一个拥有大多数List方法的准系统接口(AddRange()除外),并且它不限制您使用特定的List类型,这样您的API使用者就可以使用自己的IList自定义实现器。
为了获得更大的灵活性,请考虑在适当的时候将一些集合公开给IEnumerable。
- 对于Web服务(方法不能返回/接受接口),您会推荐什么?
- kpollock——不幸的是,SOAP Web服务会将任何IList转换为类型为t[]的数组——>序列化不支持通用列表类型。
- 仅仅因为你使用了ilist,并不意味着你保存了任何内存,如果这就是你想要的。您用new list(新列表)实例化它,ilist变量仍然指向内存中的列表。除此之外,我认为封装集合而不是直接暴露于客户机代码通常是有益的。
- 当然,@jlafay,但这不是答案的关键所在——关键是有其他的ilist或ienumerable的实现者可以指向变量,我认为这也是fxcop的关键所在。另一方面,可以修改fxcop规则以忽略此特定规则;)
- 不过,小心使用IList。Array也执行IList,将对Add和Remove提出例外。这可能会让人困惑,因为很多人都不希望这样。
- @Matthijswesels同意,数组对iList来说是个大问题-请参阅我的答案stackoverflow.com/a/36570307/1154384
主要有两个原因:
- list是一个相当膨胀的类型,许多成员在许多场景中都不相关(对于公共对象模型来说太"忙")。
- 类是未密封的,但不是专门设计为要扩展的(不能重写任何成员)
- 完全正确。这里有一个链接到krzysztofcwalina关于这个主题:blogs.msdn.com/kckwalina/archive/2005/09/26/474010.aspx
只有在编写一个将被成千上万的开发人员使用的API时,才认为这是一个糟糕的实践。
.NET框架设计指南适用于Microsoft的公共API。
如果有一个API没有被很多人使用,那么应该忽略这个警告。
- 你知道的。。。我在那里完全错了…我更新了我的答案。
- 嗯……然后我会删除我的评论,这不再相关了。:)
- 虽然某些fxcop规则确实是框架设计指南,可能不适用于某些项目,但即使是为小团队设计的库也可以从中受益。您是否曾告诉过5个开发人员,他们将不得不更改他们的项目,因为您需要对库进行一个突破性的更改(比如说观察@kaagle提到的更改)?您的团队中的开发人员是否做过您不希望做的事情,比如修改您打算只读的列表属性的内容?
- 如果指导原则在您的情况下没有意义,请在fxcop项目中禁用它-但首先仔细检查指导原则的原因。
我认为你不希望你的消费者在你的退货中加入新的元素。API应该是清晰和完整的,如果它返回一个数组,它应该返回准确的数据结构。我不认为它与t per say有关,而是直接返回一个列表<>而不是数组[]
- - 1。特别是,属性不应返回数组。虽然在一般集合中,方法可以是可枚举序列和接口,但对于C来说,它们更为惯用。
其中一个原因是用户可以更改列表,并且列表的所有者不知道这一点,而在某些情况下,在列表中添加/删除项目后,它必须做一些事情。即使现在不需要,将来也会成为一种需求。因此,最好将addxxx/removexxx方法添加到类的所有者,并公开一个IEnumerable列表,或者(在我看来更好)将其公开为IList,并使用来自WindowsBase的ObservableCollection。
- 将List暴露为IList或IEnumerable并不能防止用户修改列表(在IEnumerable的情况下进行强制转换之后)。如果要返回不可变列表,请返回ReadOnlyCollection或使用IEnumerable.AsReadOnly(),可以返回IList。
一个原因是因为列表不是你可以模拟的东西。即使在不太流行的库中,我也看到过由于这个建议而将列表对象作为IList公开的迭代,并且在以后的版本中,决定根本不将数据存储在列表中(可能存储在数据库中)。因为它是一个IList,所以更改客户机下的实现并保持每个人工作并不是一个破坏性的更改。