题
从函数返回多个相同类型的对象时,首选的容器类型是什么?
返回一个简单的数组(比如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使用aHashSet<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>
不能保证对象是不可变的。
我的建议是用<=>
包装返回的对象