某些上下文:我想编写一个类,其中向集合添加内容的主要方法是通过名为Add(或类似的东西)的方法(或方法)。所以最好的签名是params object []。在内部,这个函数必须切换/ if-else它可以接受的所有类型。所以,最初它可以接受这个object []数组,但我可能希望看到它也接受object [] []和object [] [] []等,然后方法/函数可以在内部展平,所以在调用此函数之前,用户不需要这样做。
因此...
是否可以编写一个可以接受单一类型对象的各种级别列表类型的函数? 作为一个附带问题,在设计类的接口时,最好接受(编辑:来自问题因为已经足够了。)object[]
或IEnumerable<object>
或params object[]
?
例如,我正在考虑一个接受object[]
,IEumerable<object>
的所有/全部,以及可能进一步嵌套的函数:IEnumerable<IEnumerable<object>>
,object[][]
(和on,on and on等)。
这可能吗?
答案 0 :(得分:16)
您会注意到List<T>
类本身有方法Add,它采用T和AddRange,它采用T序列。出于两个原因,我们不会尝试重载Add来做两者。首先,因为添加一个东西并添加一堆东西在逻辑上是不同的,其次,因为它极大地使重载分辨率复杂化。
如果你想要一个采用T序列的方法,那么写一个采用T序列的方法。如果调用者有一系列序列,则让它们变平;不要试图代表他们如何有效地猜测。
哪个更好:接受
object[]
或IEnumerable<object>
或params object[]
?
我们怎么知道?我们不是那个叫方法的人。你应该问的人就是要编写代码来调用你方法的人。
答案 1 :(得分:2)
一种选择就是制作一个功能,然后多次重载它。您可以使重载函数调用“基本”函数。
DoWork(params object[] args)
{
//do the actual work
}
DoWork(IEnumerable<object> args)
{
DoWork(args.ToArray());
}
//etc etc
答案 2 :(得分:1)
对一个函数进行两次重载,一次接受IEnumerable<T>
,另一次接受params T[]
。通过调用前者来实现后者。忘记嵌套,LINQ可以使用SelectMany
轻松地展平集合。
答案 3 :(得分:1)
这实际上取决于列表类型的含义。如果您明确表示,那么您可以使用接受IList<T>
的方法。如果你想将数组放入混合中,那么你应该真的接受IEnumerable<T>
。除非您需要修改它,否则数组将无法正常工作,因此您可以接受ICollection<T>
。