从函数返回多个相同类型的对象时,首选的容器类型是什么?

返回一个简单的数组(比如MyType [])是不是很好,或者你应该将它包装在一些通用的容器中(比如ICollection <!> lt; MyType <!> gt;)?

谢谢!

有帮助吗?

解决方案

Eric Lippert有一个很好的文章就此而言。如果您无法阅读整篇文章,答案是:返回界面。

其他提示

使用 IEnumerable<T> 返回yield return

我会返回一个IList<T>,因为它可以为您的功能消费者提供最大的灵活性。这样,如果您的函数的使用者只需要枚举他们可以这样做的序列,但是如果他们想要将序列用作列表,他们也可以这样做。

我的一般经验法则是接受限制性最小的类型作为参数,并返回最丰富的类型。当然,这是一种平衡行为,因为您不想将自己锁定到任何特定的接口或实现中(但总是尝试使用接口)。

这是API开发人员可以采取的最不放肆的方法。由您来决定您的函数的消费者将如何使用他们发送给您的内容 - 这就是为什么您会在这种情况下返回IEnumerable<T>以给予他们最大的灵活性。同样出于同样的原因,您永远不会想知道消费者会向您发送什么类型的参数。如果您只需要迭代作为参数发送给您的序列,则将参数设为List<T>而不是<=>。


编辑(一氧化碳):由于问题似乎不会被关闭,我只想添加其他问题的链接:为什么数组有害

为什么不List<T>

在其他人提到的Eric Lippert帖子中,我想我会强调这一点:

  

如果我需要一个序列我<!>#8217;将使用   IEnumerable<T>,如果我需要映射   从连续数字到数据I <!>#8217; ll   如果我需要映射,请使用Dictionary<K,V>   跨任意数据I <!>#8217; ll使用a   HashSet<T>,如果我需要一套我<!>#8217; ll   使用<=>。我只是不喜欢<!>#8217;需要   任何东西的数组,所以我几乎从不   使用它们。他们不会解决我的问题   比我的其他工具更好   处置。

如果要返回的集合是只读的,这意味着您永远不希望更改集合中的元素,请使用IEnumerable<T>。这是不可变的只读序列(至少从枚举本身的角度来看)元素的最基本表示。

如果您希望它是可以更改的自包含集合,请使用ICollection<T>IList<T>

例如,如果要返回搜索特定文件集的结果,请返回IEnumerable<FileInfo>

但是,如果您想公开目录中的文件,则会公开IList/ICollection<FileInfo>,因为您可能希望更改集合的内容。

我听到的一条很好的建议是:

  

在你接受的内容中保持自由,在你所提供的内容中保持准确。

在设计API方面,我建议你应该返回一个接口,而不是具体类型。

采用您的示例方法,我将其重写如下:

public IList<object> Foo() 
{
    List<object> retList = new List<object>();
    // Blah, blah, [snip]
    return retList;
}

关键是您的内部实现选择 - 使用List - 不会向调用者显示,但您将返回适当的接口。

Microsoft自己的框架开发指南建议不要返回特定类型,有利于接口。 (对不起,我找不到这个链接)

同样,您的参数应该尽可能通用 - 而不是接受数组,接受适当类型的IEnumerable。这与数组以及列表和其他有用类型兼容。

再次采用您的示例方法:

public IList<object> Foo(IEnumerable<object> bar) 
{
    List<object> retList = new List<object>();
    // Blah, blah, [snip]
    return retList;
}
return ICollection<type>

泛型返回类型的优点是,您可以在不更改使用它的代码的情况下更改底层实现。返回特定类型的优点是,您可以使用更多特定于类型的方法。

始终返回向调用者提供最大功能的接口类型。所以在你的情况下ICollection<YourType>应该被使用。

值得注意的是,BCL开发人员实际上在.NET框架的某个地方出错了 - 请参阅这篇Eric Lippert博客文章

为什么不IList<MyType>

它支持直接索引,这是数组的标志,但没有消除某天返回List<MyType>的可能性。如果要取消此功能,可能需要返回IEnumerable<MyType>

这取决于您打算如何处理您正在返回的收藏品。如果您只是迭代,或者您只想让用户进行迭代,那么我同意@Daniel,返回IEnumerable<T>。但是,如果您确实希望允许基于列表的操作,我将返回IList<T>

使用泛型。与其他集合类进行互操作更容易,类型系统更能帮助您解决潜在的错误。

返回阵列的旧风格在仿制药之前是一个拐杖。

什么使您的代码更易于阅读,可维护且更易于使用。 我会使用简单的数组,大多数时候更简单==更好。 虽然我真的必须看到上下文给出正确的答案。

有利于IEnumerable优于其他任何东西,因为这为您提供了最大的实现灵活性,并允许您使用yield return或Linq运算符进行延迟实现。

如果来电者想要List<T>,他们可以简单地对您返回的内容致电ToList(),整体表现与您创建并从您的方法中返回新<=>大致相同。

数组是有害的,但ICollection<T>也是有害的。

ReadOnlyCollection<T>不能保证对象是不可变的。

我的建议是用<=>

包装返回的对象
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top