IList<> 返回类型而不是 List<>

Posted

技术标签:

【中文标题】IList<> 返回类型而不是 List<>【英文标题】:IList<> returned type instead of List<> 【发布时间】:2015-07-31 11:12:34 【问题描述】:

我在依赖Injecting a Controller 的一个示例中找到了这种方法。使用接口类型IList&lt;&gt;而不是List&lt;&gt;的原因是什么?

public IList<string> GetGenreNames()

    var genres = from genre in storeDB.Genres
                 select genre.Name;
    return genres.ToList();

【问题讨论】:

这允许您在不影响其用户的情况下更改方法实现。查看LSP principle 如果您需要支持使用 application/xml mime 类型编码此方法的返回值,请务必测试您的设置。通常用于处理此序列化的 XmlSerializer 可能不支持序列化 List. 【参考方案1】:

实际的原因,你要去问问那个方法的原程序员

不过,我们可以想出一个合理的理由。

输入参数应尽可能开放和通用。如果您可以使用任何可以枚举的集合类型,请不要使用数组。 (即,如果您要做的只是foreach,则更喜欢IEnumerable&lt;int&gt; 而不是List&lt;int&gt;) 输出参数和返回类型应尽可能具体,但尽量在不牺牲性能或安全性的情况下返回最可用和最灵活的数据类型。如果您可以返回专门为结果创建的数组或列表(如int[]List&lt;int&gt;),则不要返回只能枚举的集合(如IEnumerable&lt;int&gt;)。

互联网上的许多地方都列出了这些指南(虽然用不同的词),并且可以帮助人们编写好的 API。

IList&lt;T&gt; 优于 List&lt;T&gt; 的原因是您返回的集合可以是:

枚举(流式访问) 按索引访问(随机访问) 修改(添加、删除等)

如果您要返回List&lt;T&gt;,您实际上不会添加任何值,除了返回一个具体类型而不是恰好实现该接口的 any 类型。因此,最好返回接口而不是具体类型。您不会丢失任何外部有用的功能,并且您仍然保留将来用不同的东西替换返回的实际对象的可能性。

【讨论】:

如果您使用 web api 并且支持 application/xml 并且您返回 IList 您可能会遇到问题。 ***.com/questions/17114175/… IList 不保证它是可修改的。不保证实现添加/删除,并且在调用添加/删除1 之前需要检查 IsFixedSize 和 IsReadOnly 属性。除了 AddRange 等额外的便利方法之外,返回 List 的附加价值是保证它永远不会是只读的。根据我的经验,客户几乎总是在收到的 IList 上调用 ToList,这会导致不必要的副本。 我同意接口对于 API 来说更整洁,但微软严重搞砸了集合接口,导致这个废话【参考方案2】:

定位接口总是比定位具体类型好。

所以如果返回 IList,这意味着任何实现 IList 的东西都可以返回,提供更好的分离。

查看这里了解更多信息

Why is it considered bad to expose List<T>?

【讨论】:

【参考方案3】:

这是 OOP 中的一些基本规则。最好有一个接口,这样您的客户(GetGenreNames 的调用者)只知道如何调用(函数签名、唯一要记住的东西,而不是实现细节等)来获得服务。

接口编程支持 OOP 的所有优点。它更通用,保持关注点分离,更可重用。

【讨论】:

以上是关于IList<> 返回类型而不是 List<>的主要内容,如果未能解决你的问题,请参考以下文章

asp.net 通过反射的一个方法,得到返回值,是object 类型的。怎么遍历里边的IList?

如何知道 propertyInfo 是不是属于 C# 中的 IList 类型?

如何对 IList<T> 执行二进制搜索?

C#IList更新问题

返回另一个类中的 IList<GenericClass> 属性

ReSharper 和隐式类型变量