Why cant I use an IEnumerable with params? Will this change in the future?
If it were 'fixed' they would have to call it something other than IEnumerable. You can't change an interface unless you have the option of recompiling everthing that uses it.
The params parameters are sent as an array, and an IEnumerable<T>
doesn't provide the random access that is required to act as an array.
You have to create the array from the IEnumerable when you call the method:
TheMethod(theIEnumerable.ToArray());
Ah, I think I may now have understood what you mean. I think you want to be able to declare a method like this:
public void Foo<T>(params IEnumerable<T> items)
{
}
And then be able to call it with a "normal" argument like this:
IEnumerable<string> existingEnumerable = ...;
Foo(existingEnumerable);
or with multiple parameters like this:
Foo("first", "second", "third");
Is that what you're after? (Noting that you'd want the first form to use T=string
, rather than T=IEnumerable<string>
with a single element...)
If so, I agree it could be useful - but it's easy enough to have:
public void Foo<T>(params T[] items)
{
Foo((IEnumerable<T>) items);
}
public void Foo<T>(IEnumerable<T> items)
{
}
I don't find I do this often enough to make the above a particularly ugly workaround.
Why cant I use an IEnumerable with params?
In order for a feature to be used by you it needs to be thought of, designed, specified, implemented, tested, documented and shipped.
The "params enumerable" feature has been thought of and designed. It has never been specified, implemented, tested, documented or shipped.
Therefore, you cannot use the feature.
UPDATE: I should clarify what I mean by "the feature" since it is possible we all have different ideas in our heads what "the feature" is. The feature I'm talking about is to allow you to say something like
void Frob(params IEnumerable<int> x)
{
foreach(int y in x) ...
}
and then the call site can either be in the "normal form" of passing a sequence of integers, or the "expanded form" of Frob(10, 20, 30). If in the expanded form, the compiler generates the call as though you'd said Frob(new int[] { 10, 20, 30}), the same as it does for param arrays. The point of the feature is that it is often the case that the method never uses random access to the array, and therefore, we could weaken the requirement that the params be an array. The params could just be a sequence instead.
You can do this today by making an overload:
void Frob(params int[] x) { Frob((IEnumerable<int>)x); }
void Frob(IEnumerable<int> x)
{
foreach(int y in x) ...
}
which is a bit of a pain. We could simply allow you to use IEnumerable as the type of the params argument and be done with it.
Will this ever be fixed?
I hope so. This feature has been on the list for a long time. It would make a lot of functions work much more nicely with LINQ.
Frob(from c in customers select c.Age);
without having to write two different versions of Frob.
However, it is a mere "small convenience" feature; it doesn't actually add a whole lot of new power to the language. That's why its never made it high enough on the priority list to make it to the "specification is written" stage.
I really wish they would rewrite the old libraries to use generics.
Comment noted.