-3

Some context: I'd like to write a class where the main method for adding things to a collection is through a method (or methods) that are named Add (or something like that). And so the signature that seems best is params object[]. Internally, this very function would have to switch/if-else all the types that it can accept. So, initially it could accept this object[] array, but I might like to see it also accept object[][], and object[][][], etc, and then the method/function could flatten internally, so the user wouldn't need to do that prior to calling this function.

So...

Is it possible to write a function that can accept various Levels of List types for a single kind of object? As a side question, when designing an interface to a class, which is better to accept object[] or IEnumerable<object> or params object[]? (Edit: struck from the question because there is already enough going on.)

For instance, I'm thinking of a function that accepts both/all of object[], IEumerable<object>, and possibly further nesting like: IEnumerable<IEnumerable<object>>, object[][] (and on, on and on, etc).

Is this possible?

lucidquiet
  • 6,124
  • 7
  • 51
  • 88
  • 4
    Anything is possible, but we may need more information. Is your question that you'd want to be able to take any sequence of some type T? Or really any sequence of anything (that is, of any type). That is, are you more concerned with T[] vs List vs HashSet or with T[] vs List vs HashSet? – James Michael Hare Jan 09 '12 at 19:03
  • 2
    There is no universal answer to this question. It really matters what you are trying to achieve. – Olivier Jacot-Descombes Jan 09 '12 at 19:09

4 Answers4

16

You'll notice that the List<T> class itself has methods Add that takes a T and AddRange that takes a sequence of T. We do not attempt to overload Add to do both, for two reasons. First, because adding a thing and adding a bunch of things are logically different, and second, because it greatly complicates overload resolution.

If you want a method that takes a sequence of T, then write a method that takes a sequence of T. If the caller has a sequence of sequences, make them flatten it; don't try to guess on their behalf how to do so effectively.

which is better: to accept object[] or IEnumerable<object> or params object[]?

How on earth should we know? We're not the ones calling the method. The person you should be asking is the person who is going to be writing code to call your method.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
2

One option is just to make one function and then overload it however many times you need. You can make the overloaded functions call the "base" function.

DoWork(params object[] args)
{
  //do the actual work
}

DoWork(IEnumerable<object> args)
{
  DoWork(args.ToArray());
}

//etc etc
jb.
  • 9,921
  • 12
  • 54
  • 90
1

Make two overloads of one function, one that accepts IEnumerable<T>, and one that accepts params T[]. Implement the latter by calling the former. Forget the nesting, LINQ can flatten collections easily using SelectMany.

millimoose
  • 39,073
  • 9
  • 82
  • 134
1

It depends really on what you mean by list types. If you mean it explicitly, then you could have a method that accepts IList<T>. If you'd like to throw arrays into the mix, then you should really be accepting IEnumerable<T>. Unless you need to modify it, in which case arrays won't really work, so you could accept ICollection<T>.

Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142