Microsoft集合指南:对几个部分感到困惑

11

我正在查看Microsoft的《集合指南》,但有些部分让我难以理解:

X 不要在公共API中使用 ArrayListList<T>。这是否意味着我应该完全避免返回 List<T>,或者我可以将其作为 IEnumerable/IList 返回,但不能显式地返回 List<T>

✓ 尽可能使用最不特定的类型作为参数类型。大多数接受集合作为参数的成员使用 IEnumerable<T> 接口。在看到ReSharper抱怨“可能对IEnumerable进行多个枚举”后,我认为当我期望预先计算的有限对象集合(而不是惰性流)时,使用ICollection<T>更好。这不是事实吗?

✓ 对于表示读/写集合的属性或返回值,请使用 Collection<T>Collection<T>的子类。为什么不使用ICollection<T>?我认为接口比具体类更可取。


请注意,这些指南是在2008年编写的,并且没有针对.NET 3.5及C# 3.0之后的版本进行更新。特别是这些建议是在2010年C# 4.0引入协变和逆变之前编写的。 - Scott Chamberlain
1个回答

9
这些指南的存在是为了促进设计方法具有参数灵活性和返回类型的灵活性。
如果从一个方法返回一个List<T>,那么该方法永远不能返回任何不是List<T>的东西。这在某些情况下可能没问题,但在其他情况下可能不行。例如,考虑一个返回在某个特定期间内登录的用户集合的方法。如果该方法只返回一个List<T>,则必须在单次遍历中获取并返回所有用户,因为这就是List的语义:一旦该方法返回,您将获得所有项目以及总计数。如果用户数量达到几万个,则可能会出现问题——获取所有记录可能需要很长时间,而且可能会占用大量内存。
如果该方法返回一个IEnumerable<T>,则不存在计数或一次性获取所有项的承诺,调用方可以迭代项目集合,但不能一次性获取所有项。这允许被调用方法返回一个对象(实现IEnumerable<T>),该对象分批收集数据并按请求逐一返回它们。
此外,许多不同的集合类型实现了IEnumerable<T>,因此另一种实现该方法的方法实际上可能决定返回一个列表实例,强制转换为IEnumerable<T>。调用方法不会知道或关心,因为它所期望的只是一个IEnumerable<T>。这不适用于硬编码列表类型-它不能被换成其他任何东西,因为它已经是尽可能具体的。
总的来说,通常情况下,泛型集合接口将是任何方法最灵活的输入参数/返回类型-接口将允许您以多种方式实现它,模拟它等等,因此您有很大的灵活性来控制传递或返回的内容。接口也没有(必要地)存在可能变得不便的语义限制。
至于第一个建议,在.NET 2.0之后,ArrayList是一种可怕的类型,绝不应该使用,因为泛型类型在各个方面都更优秀。

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