【问题标题】:Best practice when returning an array of values (.NET)返回值数组时的最佳实践 (.NET)
【发布时间】:2009-02-20 15:50:14
【问题描述】:

通常我的方法如下:

public List<int> Method1(int input)
{
    var output = new List<int>();
    //add some items to output
    return output;
}

但 FxCop 建议使用另一个 IList 实现而不是 List,但我不记得是哪个。替代方法包括将其作为 IList、ICollection 或 IEnumerable 返回,以获得更大的灵活性或完全不同的方式,如下面的代码:

public int[] Method2(int input)
{
    var output = new List<int>();
    //add some items to output
    return output.ToArray();
}

在所有备选方案、所有提供的所有可能性中,哪一个被认为是最佳实践?

【问题讨论】:

    标签: .net arrays generics


    【解决方案1】:

    IEnumerable / IEnumerable 除非你特别需要一个列表,那么你应该返回 IList

    【讨论】:

    • 我同意,但你能详细说明原因吗?
    • 因为它允许您在需要时更改函数内部的实现细节,而不会破坏调用该函数的代码。
    • 例如,也许现在您实际上返回了一个数组,但在将来的某个时候您更新代码以返回一个 List。如果您只承诺返回 IEnumerable,那么调用代码仍然可以正常工作。
    【解决方案2】:

    第 8.3.1 节中的“框架设计指南”(第 2 版)对集合作为返回值有很多话要说,总结:

    • 请勿提供可设置的集合属性。
    • 使用Collection&lt;T&gt;Collection&lt;T&gt; 的子类作为表示读/写集合的属性或返回值。
    • 使用ReadOnlyCollection&lt;T&gt;ReadOnlyCollection&lt;T&gt; 的子类)或在极少数情况下使用IEnumerable&lt;T&gt; 来表示表示只读集合的​​属性或返回值。

    (还有更多,但这三个抓住了核心)。

    上面的第一个:不要返回对内部集合的引用,除非您希望用户能够更改它(然后您可能应该有一个自定义类型,以便您有一定程度的控制)。

    我会返回 IList&lt;T&gt; 并确保我没有定义要返回的实际类型,除非我返回的是迭代器(当我使用 IEnumerable&lt;T&gt; 时)。

    【讨论】:

      【解决方案3】:

      Eric Lippert 有一篇很好的帖子说明了为什么 returning an array is usually a bad idea

      通常情况下,您应该尽可能地笼统,而不会让任何将要调用您的方法的人感到过分悲伤。优先选择接口而不是具体类,并选择最通用的接口。

      返回接口可以更好地封装您的实现,并使将来更容易更改。如果您从具体类型开始,您承诺始终返回该类型。

      IEnumerable&lt;T&gt; 是最好的起点。随着 LINQ 的出现,调用者只需给出一个枚举就可以轻松完成很少的事情。如果来电者偶尔需要一个列表,拨打.ToList() 很容易。

      如果调用者可能特别需要索引返回的集合,或者他们可能想要自己修改集合(插入/删除/重新排序项目),请考虑使用IList&lt;T&gt;

      【讨论】:

        【解决方案4】:

        ReadOnlyCollection&lt;T&gt; 是另一种选择。

        【讨论】:

        • 但前提是您不想让调用者有机会更新列表。无论如何 +1 给你的答案。
        【解决方案5】:

        在调用该方法的代码中返回你需要的接口。

        如果您需要对结果进行列表操作,请返回IList&lt;T&gt;。 如果只需要枚举结果,返回IEnumerable&lt;T&gt;

        实际上,这些是我最常用的。 除非有很好的理由,否则我从不从公共接口返回数组。

        【讨论】:

          【解决方案6】:

          视情况而定。

          您希望调用者能够修改项目并让您看到这些更改吗?可以修改数组。 IList 接口定义了用于修改的方法(但实现可能不允许这样做)。

          您能否详细说明 FxCop 警告?

          肯特

          【讨论】:

          • FxCop 建议您返回 ReadOnlyCollection 而不是 List
          • 看来。 . .奇怪的。就像我说的,如果你真的希望调用者能够修改内容怎么办?
          • "不要在对象模型中公开 List。请改用 Collection,ReadOnlyCollection 或 KeyedCollection。List 旨在从实现中使用,不在对象模型 API 中。List 以长期版本控制为代价进行性能优化。 ....
          • ... 例如,如果您将 List 返回给客户端代码,那么当客户端代码修改集合时,您将永远无法收到通知。"
          • 这在 CA1002 DoNotExposeGenericLists(设计规则)中。求助:msdn2.microsoft.com/ms182142(VS.90).aspx
          【解决方案7】:

          这取决于您的要求。综上所述,强类型数组的迭代是所有集合类型中最快的。如果您不需要调整/添加/搜索它们,数组就很好了。

          【讨论】:

            【解决方案8】:

            我几乎总是选择List,因为它提供了我经常发现最有用的方法。

            返回IEnumerable 的一个潜在负面后果是枚举时引发的任何异常都来自可能与实际构建对象的代码相距甚远的代码区域,从而使错误跟踪变得更加困难。

            【讨论】:

            • List 对于诸如“查找”之类的事情在 LINQ 之前是很方便的,但 3.5 之后并没有给你任何你不能从标准 IEnumerable 扩展方法中得到的东西。
            猜你喜欢
            • 2015-09-01
            • 2018-11-01
            • 1970-01-01
            • 2017-07-23
            • 2019-07-16
            • 1970-01-01
            • 1970-01-01
            • 2021-11-14
            • 2015-07-02
            相关资源
            最近更新 更多