views:

239

answers:

5

So, many times we have a function that accepts an IEnumerable or ICollection as a parameter. In cases where we have single items, but no collection to hold them, we must create a collection before passing them to the function, like:

T o1, o2, o3;
Foo(new T[] { o1, o2, o3 });

I've always created an array or a list, like I've done in the last example. But I wonder, is there a more elegant way to create the required IEnumerable or ICollection?

It would be quite cool, if one could do this:

Foo({ o1, o2, o3 });

And the compiler would create the most abstract possible collection that would satisfy the needs of IEnumerable or ICollection (depending on which one the function accepts).

Anyhow, how you would pass o1, o2 and o3 to an IEnumerable or ICollection parameters?

+1  A: 

Assuming Foo expects an IEnumerable<T>, you can take advantage of type inference and do:

T o1, o2, o3;
Foo(new []{o1, o2, o3});
theprise
+7  A: 

The current version of C# (3) supports a notation without explicit type, i.e.

Foo(new [] { o1, o2, o3 })

to create an array. There’s also Linq’s Enumerable.Range to create a continuous range of numbers. Everything else has to be implemented. In the spirit of Java:

public static IEnumerable<T> AsList<T>(params T[] values) {
    return values;
}

to be called like this:

Foo(Enumerable.AsList(o1, o2, o3));
Konrad Rudolph
+2  A: 

Sometimes I've used a method with a "params" argument.

Foo(params T[] ts)

And if I'm dead set on IEnumerable I just have that method delegate to the one that wants IEnumerable.

Foo(params T[] ts) { Foo(ts.AsEnumerable()); }

You have to call AsEnumerable or you're going to recurse.

Mike Two
+1  A: 

Creating an array and passing that is probably the simplest/most elegant way to accomplish this in the current version of C#. You can take advantage of implicit array typing (i.e. new[] { ... }, but that's as far as it goes.

I suspect you're really looking for the C# equivalent of this F# syntax:

let foo = seq [ o1; o2; o3 ]

which generates an IEnumerable<T> that will iterate over the specified elements. ('Seq' is actually the F# alias for 'IEnumerable`, though F# has built-in support for them.)

Unfortunately, since this is a largely functional notion, there is no C# equivalent - though who knows when it will be added, as C# becomes more and more functional.

Noldorin
A: 

If you have a method that takes an array as its last parameter, it may make sense to mark that parameter params. This lets you call the method like this:

Foo(o1, o2, o3);

I find this particularly helpful when writing a unit test for Foo(), because often in a unit test my parameters are separate like this, instead of in an array.

I advise against doing this if there is an overload of Foo() that doesn't take an array in that position, because it can get confusing quickly.

I do wish that the C# language allowed params for IList<T>:

void Foo(params IList<T> ts) { ... }
Jay Bazuzi