Reputation: 27995
I know IEnumerable has been discussed several times here but I couldn't find the answer to my specific question so I'm bringing it up as a new question.
Consider the following piece of code:
static void Main(string[] args)
{
List<string> testList = new List<string> {"Test", "Test1", "Test1"};
IEnumerable<string> filtered = testList.Where(x => x == "Test1");
DoSomeWork(filtered);
DoSomeMoreWork(filtered);
}
public static void DoSomeWork(IEnumerable<string> items)
{
foreach (var item in items)
{
Console.WriteLine("do some work");
}
}
public static void DoSomeMoreWork(IEnumerable<string> items)
{
foreach (var item in items)
{
Console.WriteLine("do some more work");
}
}
Am I right, that this causes not only the two items in "filtered" to iterate two times but actually the items in "testList"? So, considering that "testList" was a big list with 10000 items and "filtered" reduces it to 10 items, it would be more clever to make "filtered" a list (aka use var and just append ToList() at the end)
EDIT: That's the most embarrassing question I ever asked here. I knew it would be bad to iterate an IQueryable for example because this would result in fetching the data twice from the DB. However I wasn't exactly sure about in memory lists. I would delete the question if I could ;-)
Upvotes: 6
Views: 3531
Reputation: 39898
The big list will be reiterated twice. To check that this really happens change your query to:
List<string> testList = new List<string> { "Test", "Test1", "Test1" };
IEnumerable<string> filtered = from t in testList
where t == "Test1"
select t;
If you then set a breakpoint on the 'where t == "Test1" part, you will see that the debugger hits this line for both the iterations.
Upvotes: 7
Reputation: 176896
List is ultimatly inherit from IEnumrable check this
public class List<T> : IList<T>, ICollection<T>,
IEnumerable<T>, IList, ICollection, IEnumerable
One more thing you can create list of IEnurable using the following constructor avaialble
public List(
IEnumerable<T> collection
)
EDIT
The derivedi.e filtered list is get iterated twice by the both methods but append .ToList() method at the end .
IEnumerable<string> filtered = testList.Where(x => x == "Test1").ToList();
http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx
Upvotes: 0
Reputation: 19465
it would be more clever to make "filtered" a list (aka use var and just append ToList() at the end)
Yes, especially in terms of Linq-To-Entities etc.
Returning an IEnumerable
with linq allows for differed execution. When you do append ToList()
to the end, your list is returned right there.
See http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx
Upvotes: 0
Reputation: 111850
The big list will be reiterated twice. if you don't want it, you can "materialize" the restriction.
var filtered = testList.Where(x => x == "Test1").ToList();
And there are many answers that tell you this. You should have searched better :-)
Upvotes: 1