The implementation is almost exactly the same as IEnumerable<T>. ToArray() . ToList() simply creates a new List that contains a private array that is added to during each iteration.
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.
Then ToList() method is called to force immediate query evaluation and return a List<T> containing the query results. That's all about cloning a List in C#.
LINQ ToList() Method In LINQ, the ToList operator takes the element from the given source, and it returns a new List. So, in this case, input would be converted to type List.
Yes, ToList
will create a new list, but because in this case MyObject
is a reference type then the new list will contain references to the same objects as the original list.
Updating the SimpleInt
property of an object referenced in the new list will also affect the equivalent object in the original list.
(If MyObject
was declared as a struct
rather than a class
then the new list would contain copies of the elements in the original list, and updating a property of an element in the new list would not affect the equivalent element in the original list.)
From the Reflector'd source:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
So yes, your original list won't be updated (i.e. additions or removals) however the referenced objects will.
ToList
will always create a new list, which will not reflect any subsequent changes to the collection.
However, it will reflect changes to the objects themselves (Unless they're mutable structs).
In other words, if you replace an object in the original list with a different object, the ToList
will still contain the first object.
However, if you modify one of the objects in the original list, the ToList
will still contain the same (modified) object.
The accepted answer correctly addresses the OP's question based on his example. However, it only applies when ToList
is applied to a concrete collection; it does not hold when the elements of the source sequence have yet to be instantiated (due to deferred execution). In case of the latter, you might get a new set of items each time you call ToList
(or enumerate the sequence).
Here is an adaptation of the OP's code to demonstrate this behaviour:
public static void RunChangeList()
{
var objs = Enumerable.Range(0, 10).Select(_ => new MyObject() { SimpleInt = 0 });
var whatInt = ChangeToList(objs); // whatInt gets 0
}
public static int ChangeToList(IEnumerable<MyObject> objects)
{
var objectList = objects.ToList();
objectList.First().SimpleInt = 5;
return objects.First().SimpleInt;
}
Whilst the above code may appear contrived, this behaviour can appear as a subtle bug in other scenarios. See my other example for a situation where it causes tasks to get spawned repeatedly.
Yes, it creates a new list. This is by design.
The list will contain the same results as the original enumerable sequence, but materialized into a persistent (in-memory) collection. This allows you to consume the results multiple times without incurring the cost of recomputing the sequence.
The beauty of LINQ sequences is that they are composable. Often, the IEnumerable<T>
you get is the result of combining multiple filtering, ordering, and/or projection operations. Extension methods like ToList()
and ToArray()
allow you to convert the computed sequence into a standard collection.
A new list is created but the items in it are references to the orginal items (just like in the original list). Changes to the list itself are independent, but to the items will find the change in both lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With