So basically i have this method.
public List FilterCustomersByStatus(List source, string status)
{
return (List
The difference between IEnumerable and IList is, the enumerable doesn't contain any data, it contains an iterator that goes through the data as you request the new one (for example, with a foreach loop). On the other hand, the list is a copy of the data. In your case, to create the List, ToList() method iterates through the entire data and adds them to a List object.
Depending to the usage you are planning, both have advantages and disadvantages. For example, if you are planning to use the entire data more than once, you should go with the list, but if you are planning to use it once or you are planning to query it again using linq, enumerable should be your choice.
Edit: The answer to the question why the return type of Where is WhereListIterator instead of List is, it's partly because how Linq works. For example, if you had another Where or another Linq statement following the first, the compiler would create a single query using the entire method chain, then return the iterator for the final query. On the other hand, if the first Where would return a List that would cause each Linq method in the chain execute separately on the data.
As others pointed out, you need to use ToList
to convert the result to List<T>
.
The reason is that Where
is lazily evaluated, so Where
does not really filter the data.
What it does is create an IEnumerable
which filters data as needed.
Lazy evaluation has several benefits. It might be faster, it allows using Where
with infinite IEnumerable
s, etc.
ToList
forces the result to be converted to List<T>
, which seems to be what you want.
does the Enumerable.Where create a new instance of
WhereListIterator
Yes.
and if so why would anyone do this
Because it allows lazy streaming behavior. Where
won't have to filter all the list if its consumer wants only first or second entry. This is normal for LINQ.
because thats an unnecessary loss of performance and functionality since i always have to create a new list (.ToList())
That "loss of performance and functionality" comes from your design. You don't need List<Customer>
after filtering, because it's pointless to do any modifications on it.
Update: "why is it implemented so"
Because it it implemented over IEnumerable
, not IList
. And thus it looks like IEnumerable
, it quacks like IEnumerable
.
Besides, it's just so much easier to implement it this way. Imagine for a moment that you have to write Where
over IList
. Which has to return IList
. What should it do? Return a proxy over original list? You'll suffer huge performance penalties on every access. Return new list with filtered items? It'll be the same as doing Where().ToList()
. Return original list but with all non-matching items deleted? That's what RemoveAll
is for, why make another method.
And remember, LINQ tries to play functional, and tries to treat objects as immutables.
The Where extension filters and returns IEnumerable<TSource>
hence you need to call .ToList() to convert it back
public List<Customer> FilterCustomersByStatus(List<Customer> source, string status)
{
return source.Where(c => c.Status == status).ToList();//This will return a list of type customer
}
Try this:
public List<Customer> FilterCustomersByStatus(List<Customer> source, string status)
{
return source.Where(c => c.Status == status).ToList();
}