Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiency of ToList() [duplicate]

Tags:

A lot of the developers I work with feel more comfortable working with a List as opposed to IEnumerable (for example). I am wondering whether there is any performance impact for ToList() overuse. For example, or, will use ToList() after ordering to get a list back out again i.e.

private void ListThinger(List<T> input)
{
  input = input.OrderBy(s => s.Thing).ToList();
  foreach(var thing in input)
  {
      // do things
  }
}

My question is:

  • How efficient is the ToList() method? Will it create a new list and how much memory does that take, assuming the contents are POCOs? Does this change if its a value type rather than a POCO?
  • Will the size of the list determine efficiency or does size of list not determine cost of ToList()?
  • If a list is cast to an IEnumerable and then ToList() is called on it, will it just return the original object?

P.s. I understand that a single use of ToList won't break any backs, but we are building a highly concurrent system that is currently CPU bound so I am looking for little wins that, when scaled, will add up to a big improvement

like image 214
Chris Avatar asked Sep 14 '17 12:09

Chris


People also ask

Does ToList decrease performance?

ToList , the code calls Enumerable. ToList() which is an extension method that return new List<TSource>(source) . In the corresponding constructor, under the worst circumstance, it goes through the item container and add them one by one into a new container. So its behavior affects little on performance.

Does ToList create a copy?

ToList() makes a shallow copy. The references are copied, but the new references still point to the same instances as the original references point to.

What does ToList () do in C#?

The ToList<TSource>(IEnumerable<TSource>) method forces immediate query evaluation and returns a List<T> that contains the query results. You can append this method to your query in order to obtain a cached copy of the query results.

What is the difference between ToArray and ToList?

In the majority of scenarios ToArray will allocate more memory than ToList . Both use arrays for storage, but ToList has a more flexible constraint. It needs the array to be at least as large as the number of elements in the collection. If the array is larger, that is not a problem.


1 Answers

How efficient is the ToList() method? Will it create a new list and how much memory does that take, assuming the contents are POCOs? Does this change if its a value type rather than a POCO?

The ToList() method materializes the given collection by creating a new list and populating it with the items of the given collection. Linq.ToList() implementation:

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    return new List<TSource>(source);
}

By doing so you are not gaining the power of deffered execution if needed


Will the size of the list determine efficiency or does size of list not determine cost of ToList()?

As it calls Lists copy constructor and it creates a new list then it'll work on each of the items. So it'll run in O(n) - meaning that list's size matters. MSDNs documentation about the operation of the copy constructor:

Initializes a new instance of the List class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.

As @Jason mentioned in the comment bellow the Copy Constructor is smart and is efficient but doing it when not needed is still an O(n) operation that doesn't have to happen


If a list is cast to an IEnumerable and then ToList() is called on it, will it just return the original object?

No. It will create a new list as seen above


As for your example code:

input = input.OrderBy(s => s.Thing).ToList();
foreach(var thing in input)
{
   // do things
}

As you are getting a materialized list (rather than an IQueriable/IEnumerable that might perform in deffered execution) adding the ToList after the adding gives you no benefit.

You can look here, might also help: When to use LINQ's .ToList() or .ToArray()

like image 160
Gilad Green Avatar answered Sep 21 '22 03:09

Gilad Green