C# – ToList method in Linq

clinqperformance

If I am not wrong, the ToList() method iterate on each element of provided collection and add them to new instance of List and return this instance.Suppose an example

//using linq
list = Students.Where(s => s.Name == "ABC").ToList();

//traditional way
foreach (var student in Students)
{
  if (student.Name == "ABC")
    list.Add(student);
}

I think the traditional way is faster, as it loops only once, where as of above of Linq iterates twice once for Where method and then for ToList() method.

The project I am working on now has extensive use of Lists all over and I see there is alot of such kind of use of ToList() and other Methods that can be made better like above if I take list variable as IEnumerable and remove .ToList() and use it further as IEnumerable.

Do these things make any impact on performance?

Best Answer

Do these things make any impact on performance?

That depends on your code. Most of the time, using LINQ does cause a small performance hit. In some cases, this hit can be significant for you, but you should avoid LINQ only when you know that it is too slow for you (i.e. if profiling your code showed that LINQ is reason why your code is slow).

But you're right that using ToList() too often can cause significant performance problems. You should call ToList() only when you have to. Be aware that there are also cases where adding ToList() can improve performance a lot (e.g. when the collection is loaded from database every time it's iterated).

Regarding the number of iterations: it depends on what exactly do you mean by “iterates twice”. If you count the number of times MoveNext() is called on some collection, then yes, using Where() this way leads to iterating twice. The sequence of operations goes like this (to simplify, I'm going to assume that all items match the condition):

  1. Where() is called, no iteration for now, Where() returns a special enumerable.
  2. ToList() is called, calling MoveNext() on the enumerable returned from Where().
  3. Where() now calls MoveNext() on the original collection and gets the value.
  4. Where() calls your predicate, which returns true.
  5. MoveNext() called from ToList() returns, ToList() gets the value and adds it to the list.

What this means is that if all n items in the original collection match the condition, MoveNext() will be called 2n times, n times from Where() and n times from ToList().