Why cant I use an IEnumerable with params? Will this ever be fixed? I really wish they would rewrite the old libraries to use generics...
-
20Is this a rant or a question? – dtb Jan 24 '10 at 20:51
-
11@dtb clearly, it's both. +1 for the question. Wish I could give it a second +1 for the rant as well. – BrainSlugs83 Mar 09 '12 at 04:30
-
2@BrainSlugs83 before the edit, the question looked like rant, but for what the title of the question conveys, its a very good question.. – nawfal Apr 21 '13 at 19:27
-
2Rolled back to original question, mainly because the answer below from Eric Lippert - who was then a C# compiler dev - refers to the original wording. If he didn't take exception to the wording, we probably needn't either! – Olly Mar 07 '15 at 03:28
-
Slight nitpicking, `params array` is still generic, making it `IEnumerable` wont add to its genericity. May be you meant make it *more general* (purpose). – nawfal Jun 15 '16 at 09:09
3 Answers
Why cant I use an IEnumerable with params?
The question presupposes that the design team must provide a reason to not add a feature to the language. This presupposition is false.
Rather, in order for a feature to be used by you it needs to be thought of, designed, specified, implemented, tested, documented and shipped. All of these have large costs.
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: As of this writing -- early 2015 -- has now been specified, but implementation, testing, documentation and shipping were cut for C# 6.0 in the latter part of 2014. See Lucian's announcement here: http://roslyn.codeplex.com/discussions/568820.
Since it has still not been implemented, tested, documented and shipped, there is still no such feature. Hopefully this will make it into a hypothetical future version of C#.
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.

- 647,829
- 179
- 1,238
- 2,067
-
4Implementing this feature would basically mean an implicit call to ToArray, right? – Guffa Jan 24 '10 at 22:06
-
1@Guffa, I'm not following your train of thought. I think the answer to your question is "no" but I'm not sure what question you're asking. – Eric Lippert Jan 24 '10 at 23:08
-
@Eric: The method that takes the params needs a collection with random access (not the forward-only that the IEnumerable offers), so the IEnumerable needs to be realised into a collection that has all the items all the time. The easiest way to implement this would be to simply call ToArray on the IEnumerable (or something to the same effect). – Guffa Jan 25 '10 at 00:02
-
8Why does the callee need that, necessarily? The vast majority of methods that take params arrays that I've ever written just stuffed that thing into a foreach. – Eric Lippert Jan 25 '10 at 03:11
-
3I see this as more than just a convenience feature, because you're workaround is broken when there's a generic involved. Good to know it's at least on the radar. IMO, the params feature should have used IEnumerable in the first place (though I know at the time it wasn't an option). – Joel Coehoorn Dec 16 '10 at 15:01
-
8For something so seemingly trivial this is such a pain in the backside. A fix would greatly simplify APIs... Please fix for C# 5. Please? – Ed Blackburn Apr 06 '11 at 14:17
-
5I just hit the wish for this once again today! (This and the lack of an easy/clean way to create a single item enumerable is starting to make C# feel like a “old” language that has had linq bolted on..) – Ian Ringrose Jun 21 '11 at 12:06
-
1public static IEnumerable
Enumerate(this T o) where T : new { return new T[] {o}; } or something similar (writing out of my head) could help – Marino Šimić Mar 13 '12 at 13:58 -
@IanRingrose said "...lack of an easy/clean way to create a single item enumerable". I agree. It would be nice to type "*foo" and have it expand to "Enumerable.Repeat(foo, 1)". Some other unary operator would be acceptable! ;) – Damian Powell Apr 14 '14 at 15:16
-
I think implicitly calling ToArray() would be kind of evil as well, since it'd hide the fact that the enumeration gets fully realized just by being passed. This would make it impossible to use lazily loaded infinite lists and bothersome to send heavy db queries that don't need to be fired in all cases. – sara Dec 14 '15 at 10:44
-
Creating an additional overload is always at least a little annoyance, but sometimes, it's more annoying, e.g. when there's already a few overloads of the method for similar purposes. – McKay Jan 07 '16 at 19:12
-
It may not add a lot of power, but it would sure make a lot of situations less annoying. – jpmc26 Jan 19 '18 at 19:55
-
1So as of Today Jan 2018 is this feature available ? If not then anywhere near future ? – Ali Umair Jan 24 '18 at 11:49
-
1Still being considered as part of the span work I think. Check the github forums. – Eric Lippert Jan 24 '18 at 15:01
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.
Note that when calling the above code, you'll want to explicitly specify the type argument, to avoid the compiler preferring the params
example. So for example:
List<string> x = new List<string>();
Foo<string>(x);

- 1,421,763
- 867
- 9,128
- 9,194
-
1Are you sure you have tried this? When I do it it matches the params form first ie it matches ``public void Foo
>(params IEnumerable – bradgonesurfing Aug 20 '13 at 10:50[])`` -
-
You didn't but ``Foo
(params T[] items)`` matches first if ``T`` is ``IEnumerable – bradgonesurfing Aug 20 '13 at 11:19`` rather than ``Foo (IEnumerable items)`` -
Actually I've just tested it again and found it does work but in my slightly different code it matches the wrong one. I'll spend some more with it. – bradgonesurfing Aug 20 '13 at 11:24
-
2Ok tested it again and found where you are wrong. You have to provide exactly the type ``IEnumerable
`` rather than ``List – bradgonesurfing Aug 20 '13 at 11:39`` or the compiler prefers the ``params`` version. See https://gist.github.com/bradphelan/9fddca0fa5f1c07ba736 for an executable example -
1@bradgonesurfing: Ah, I see what you mean. That's because it's generic. If you explicitly call `Foo
` then it works in both cases. I'll edit my answer to make that clear. – Jon Skeet Aug 20 '13 at 11:44 -
5Having to specify the generic type argument is a good reason why params as IEnumerable would be a good addition to the language. – Søren Boisen Jun 22 '15 at 09:38
-
1@SørenBoisen: Agree. The compiler happily accepts it if you do not specify the generic type argument, and it only fails when running it (which is hopefully in a unit test, and not in production...). – sondergard Dec 16 '15 at 13:58
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());

- 687,336
- 108
- 737
- 1,005
-
3Why can't params parameters be set as a IEnumerable
if that is what the method writer wants? – Ian Ringrose Jun 21 '11 at 12:03 -
@Ian Ringrose: One reason is that the `IEnumerable
` interface didn't exist when `params` was added to the language. Why it hasn't been added afterwards is probably beacuse it's not such a useful feature. You can just add an overload to support both `params T[]` and `IEnumerable – Guffa Jun 21 '11 at 14:09`. -
Why the downvote? If you don't explain what it is that you think is wrong, it can't improve the answer. – Guffa Jan 08 '16 at 02:51
-
1@Guffa no you can't overload it -- the compiler gets confused when you try to call it and makes you write a bunch of extra syntax. -- We might as well just add `.ToArray()` -- which is silly. – BrainSlugs83 May 16 '18 at 01:04