【问题标题】:What is the difference between returning IList vs List, or IEnumerable vs List<Class>. I want to know which is better to return返回 IList 与 List 或 IEnumerable 与 List<Class> 有什么区别。我想知道哪个更好返回
【发布时间】:2015-01-10 13:05:36
【问题描述】:

返回 IList 与 List 或 IEnumerable 与 List 有什么区别。

我想知道哪个更好返回。

当我们需要使用一个时,它会对性能产生什么影响?

【问题讨论】:

  • 基本上,如果您使用 IList 或 IEnumerable 作为返回类型,则可以返回任何实现这些接口的对象。如果你指定一个具体的类,那么你只能返回那个特定的类型。
  • 有一些guidelines。编写高性能代码的最佳方式是编写简单易懂的代码,并拥有实际的性能目标。编写完所有内容后,测量性能,并且只有在性能不够好时,您才应该考虑避免“简单、可理解” - 但请确保您还测量了性能较差的地方和把注意力集中在那里。我从来没有遇到过更改返回数据类型会产生重大影响的情况。
  • 在性能方面,你允许你的函数返回哪种类型并不重要,重要的是你返回的是什么具体的对象。
  • 感谢 Damien 分享“收藏指南”,这是一篇非常棒的文章。
  • @DavidKlempfner 在高层次思考时,这对我来说非常有趣且不直观(尽管非常有意义),感谢您的链接

标签: c# asp.net .net asp.net-mvc vb.net


【解决方案1】:

没有一种类型可以总是更好地返回。这是您应该根据您的设计/性能/等目标做出的决定。

IEnumerable&lt;T&gt; 非常适合用于表示项目序列,可以迭代,但又不想允许修改(添加、删除等)。

IList&lt;T&gt; 为您提供使用IEnumerable&lt;T&gt; 可以获得的一切,以及让您对集合有更多控制权的操作:添加、删除、计数、索引访问等。

List&lt;T&gt;IList&lt;T&gt; 的具体实现。我会说几乎总是最好从您的方法中公开IList&lt;T&gt; 接口而不是List&lt;T&gt; 实现。这不仅仅是关于列表 - 这是一个基本的设计原则,更喜欢接口而不是具体的实现。

好的,现在关于非通用版本IEnumerable, IList, List: 它们实际上来自 .NET 框架的早期版本,使用泛型等价物会更好。

关于性能的几句话: IEnumerable&lt;T&gt;(with IEnumerator&lt;T&gt;) 实际上是一个迭代器,它允许您将一些计算推迟到以后。这意味着无需立即分配内存来存储大量数据(当然,当您在迭代器后面有数组时,情况并非如此)。您可以根据需要逐步计算数据。但这意味着这些计算可能会一遍又一遍地执行(例如,每个foreach 循环)。另一方面,使用 List 可以在内存中固定数据,并使用廉价的 Index 和 Count 操作。如您所见,一切都是为了妥协。

【讨论】:

  • 如果客户端代码调用返回IEnumerable&lt;T&gt;的方法,客户端代码现在必须避免多次枚举(例如通过调用ToList()),因为有可能(现在或将来)该方法返回一个带有延迟执行的序列——可能是缓慢、昂贵的类型。更好的是,方法应该更喜欢返回IReadOnlyCollection&lt;T&gt;,它基本上是IEnumerable&lt;T&gt;,带有一个额外的Count 属性,并且暗示没有没有延迟执行。相关(但缺少接口):msdn.microsoft.com/en-us/library/dn169389(v=vs.110).aspx.
【解决方案2】:

在方法的参数和结果中使用具体类会产生很强的依赖性,而使用接口则不会。什么意思?

如果将来您要更改类的实现,并使用SynchroinizedCollectionLinkedList 或其他东西而不是List,那么您必须更改您的方法签名,确切地说是返回值。

之后,您不仅需要重新构建使用此类的程序集,而且可能还需要重写它们。

但是,如果您使用IEnumerableIReadonlyCollectionICollectionIList 接口之一,则不必重写和重新编译客户端程序集。因此,接口总是首选参数和结果中的类。 (但请记住,我们讨论的是不同程序集之间的依赖关系。对于同一个程序集,此规则并不那么重要。)

问题是,使用什么接口?这取决于客户端类(用例)的要求。 F.e.如果您要逐个处理元素,请使用IEnumerable&lt;T&gt;,如果您需要计算元素数量,请使用IReadonlyCollection&lt;T&gt;。这两个接口都是协变的,便于类型转换。

如果您需要写能力(AddRemoveClear)或非协方差只读能力(Contains),请使用ICollection&lt;T&gt;。最后,如果您需要随机索引访问,请使用IList&lt;T&gt;

在性能方面,接口方法的调用慢了一点,但差别不大。你不应该关心这个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多