【问题标题】:Best Type to set as return type for methods that return a collection?将最佳类型设置为返回集合的方法的返回类型?
【发布时间】:2009-10-20 18:45:32
【问题描述】:

哪种类型的产品最适合我们退货?

我应该使用IList<T>IEnumerable<T>IQueryable<T> 还是别的什么?哪个最好?为什么

我正在尝试决定我应该在接口和我正在编写的几个类的实现中通常使用哪个。

edit 让我进一步确定这一点,我正在使用 LINQ to SQL 通过 WCF 服务返回数据。感觉这可能会改变使用的最佳类型?

【问题讨论】:

  • 这里有一个很好的讨论:stackoverflow.com/questions/1456132/…
  • 根据上面的评论,当使用'IEnumerable'时,我班级的消费者如何使用它?只是显式转换回'List'?
  • 不,这样的演员表会违反界面,并且很可能在某些时候失败。消费者应该使用返回的确切接口,或者它的父级。因此,例如,如果它返回 IList 并且您所需要的只是 IEnumerable 的功能,那么这就是您应该使用的。
  • 那么消费者将如何使用它?如果方法返回 IEnumerable 消费者如何调用该方法并存储结果?哪些具体的泛型类型使用 IEnumerable?
  • @Nate - 您可以将其存储为 IEnumerable。拥有 IEnumerable 类型的字段或属性非常好。感谢 LINQ,您可以使用 IEnumerable 做很多事情。您可以按索引、排序、查找(通过 Where)等进行访问。List、HashSet 和 LinkedList 是 IEnumerable 的一些具体实现。

标签: c# .net


【解决方案1】:

Framework Design Guidelines 状态:

使用Collection<T>Collection<T> 获取属性或返回 代表读/写的值 收藏。

public Collection<Session> Sessions { get; }

使用ReadOnlyCollection&lt;T&gt;,一个子类 ReadOnlyCollection&lt;T&gt; 的,或者很少见 案例IEnumerable&lt;T&gt; 用于属性或 返回值表示只读 收藏。

public ReadOnlyCollection<Session> Sessions { get; }

一般来说,更喜欢 ReadOnlyCollection&lt;T&gt;.

关于 LINQ,为 .NET 3.5 创建的指南很明确,但 (imo) 的理由并不完全令人信服:

审查机构明确表示 决定 LINQ 不应更改本指南 ["不返回IEnumerator&lt;T&gt;, 除了作为 a 的返回类型 GetEnumerator 方法"]。你的 来电者可能会变得笨拙 如果他们选择不使用对象模型 LINQ 或不支持的语言 支持一下。

【讨论】:

  • 这些是 .NET 3.5 之前的指南吗?想知道 LINQ 是否让我转向 IEnumerable
  • Lazy eval + LINQ 让我对 IEnumerable 有了更多思考
  • 当使用 'IEnumerable' 我班的消费者如何使用它?只是显式转换回'List'?
  • 非常有趣 - 我想知道为什么 ReadOnlyCollection 在只读情况下优于 IEnumerable?
  • 这本书有一年了...我倾向于 IList 或 IEnumerable
【解决方案2】:

使用所有可能的返回类型都符合的最不通用的类型。即,如果您正在查看的方法可能返回List&lt;int&gt;int[],那么我将键入IEnumerable&lt;int&gt; ...如果它可以返回List&lt;int&gt;List&lt;Employee&gt;int[]我会输入IEnumerable。如果它总是返回 Collection&lt;Employee&gt;Collection&lt;SalariedEmployee&gt;,则返回 Collection&lt;Employee&gt;

如果该方法将始终生成相同的类型,请使用该类型...

在一个消费方法或接口中,otoh,返回的对象被使用,你应该使用相反的理念,将传入的方法参数键入为最不通用使用方法中代码的内部功能所需的类型...即,如果所有方法对集合对象所做的所有操作都是使用foreach 枚举通过它,那么传入的参数类型应该IEnumerable&lt;&gt;

【讨论】:

    【解决方案3】:

    如果集合是无序的或者不需要随机访问,IEnumerable 是正确的。如果它是一个列表并且您想将其公开为一个列表,则声明方法或属性以返回 IList,但您可能需要在该集合上返回一个 ReadOnlyCollection 包装器(直接或使用诸如 List.AsReadOnly() 之类的语法) .只有当我有一些有用的覆盖时,我才会返回 IQueryable。

    【讨论】:

      【解决方案4】:

      我默认为 IEnumerable。我正在拍摄要公开的最小界面。 IList&lt;T&gt;IQueryable&lt;T&gt; 都实现了 IEnumerable&lt;T&gt;。因此,除非您对方法有其他特定要求,否则我会选择极简主义并使用最少派生类型。如果您在调用代码中有其他要求,例如索引查找的性能或获取集合中的项目数,那么您可能需要选择其他类型,例如 ICollection&lt;T&gt;

      【讨论】:

      • IEnumerable 如果您确定您唯一想要支持的方案是只向前迭代,那么它是有意义的。
      • @fatcat1111 - 你是对的,但如果我要返回一个集合,这通常是我想要支持的唯一方案。如果我想修改集合或做其他事情,那么我会为此提供描述性方法。我不会返回 IList 以便有人可以调用 Add 。我会有一个 AddEmployee 方法。
      • 这正是我的想法。这支持使用 WCF 或其他基于服务的架构。
      • @Mike 二:我同意仅将 List 作为 IList 返回会将其暴露给不需要的更改,但是返回 List.AsReadOnly() 怎么样?这使您可以获取计数、按索引访问成员等。
      • @Nate - 更像IEnumerable&lt;T&gt; result = obj.ReturnIEnumerable(); 您可以将变量声明为接口类型。它实际上使您在编写ReturnIEnumerable() 时具有更大的灵活性。它可以返回 List 或 HashSet 或 LinkedList 或者它可以执行 yield return ... 您的调用者永远不需要知道。如果 IEnumerable 的合同足够了,并且由于 LINQ 经常如此,那么将其保留为 IEnumerable
      【解决方案5】:

      在编写应用程序时,我认为返回特定的泛型类型没有任何问题,例如:

      List<myType> MyMethod()
      {
        ...
      }
      

      根据我的经验,这对原始开发人员来说很容易,其他开发人员也很容易理解原始开发人员的意图。

      但是,如果您正在开发某种将被其他开发人员使用的框架,您可能希望更复杂 - 例如返回一个接口。

      【讨论】:

      • 这种方法的主要问题是当类被更新为使用 List 以外的东西时接口会中断。小问题是暴露整个 List 允许通过插入或删除进行修改。
      • 你是对的,但根据我的经验(至少在应用程序开发中),更改类返回的集合类型相当罕见。我宁愿在以后支付重构的代价——仅在需要时,而不是预先设计我所有的集合接口。当然,您的体验可能会有所不同...
      • 我确实理解您对应用程序的重视,但我认为即使您不编写可重用组件,特别是当应用程序必须是维护和调整。
      【解决方案6】:

      这最终取决于您要如何处理返回的数据。请记住,IEnumerable 意味着(我的意思是强制)您以顺序方式访问数据。您无法添加、更改它,也无法访问数组中特定点的项目。

      IList 没有这个问题,但是你必须提供额外的功能来实现它。如果您从 .net 对象继承,您可能不必担心它,但这实际上取决于您创建对象的方式。

      每个人都有自己的取舍,没有人总是默认的。

      【讨论】:

      • 您不必在返回IList 之前收集所有数据。事实上,当我想提供随机访问和Count 属性时,我经常使用IList,但又不想花时间预先收集数据。例如,消费者可能只需要第 5 个元素,因此您不希望对数据库进行五次调用来填充项目 0-4(使用您的示例)。编写一个按需填充的IList 实现很容易。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多