Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Params IEnumerable<T> c#

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...

like image 330
Dested Avatar asked Jan 24 '10 20:01

Dested


People also ask

What is IEnumerable T in C#?

IEnumerable. IEnumerable<T> contains a single method that you must implement when implementing this interface; GetEnumerator, which returns an IEnumerator<T> object. The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property.

What is IEnumerable?

IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. It is the base interface for all non-generic collections that can be enumerated. This works for read-only access to a collection that implements that IEnumerable can be used with a foreach statement.

What is IEnumerable in ASP NET MVC?

IEnumerable will execute select query on server side, load data in-memory on client side and then filter data. IEnumerable can be used for querying data from in-memory collections like List, Array etc.

Is IEnumerable a collection?

IEnumerable<T> is an interface that represents a sequence. Now; collections can usually be used as sequences (so... List<T> implements IEnumerable<T> ), but the reverse is not necessarily true. In fact, it isn't strictly required that you can even iterate a sequence ( IEnumerable<T> ) more than once.


2 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.

like image 180
Eric Lippert Avatar answered Oct 02 '22 11:10

Eric Lippert


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); 
like image 24
Jon Skeet Avatar answered Oct 02 '22 12:10

Jon Skeet