After running this code:
var input = new List<T>( ... );
var result = input.Select( t => new U(t) );
U first1 = null;
foreach ( U u1 in result )
if ( first1 == null )
first1 = u1;
U first2 = null;
foreach ( U u2 in result )
if ( first2 == null )
first2 = u2;
Then 'first1 == first2' evaluates to false even though both U's wrap the same T. I haven't tested it yet, but I think it can be made to evaluate to true by chaining a .ToList() or .ToArray() onto the Select() call.
In real code, which is much more complex than this simple illustration, what is a good rule of thumb to use for deciding if .ToList() or .ToArray() should be appended? My initial thoughts are either any referenced expression that may be iterated more than once or, to be safer in case potential iterations are not obvious, any referenced expression whose result will never change.
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. ToArray has similar behavior but returns an array instead of a List<T>.
Use ToList before you exit the using block that holds your DataContext . Return a query when the caller is likely/obligated to supply additional filtering criteria which will be used by indexes to reduce # of result rows and/or database IO.
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.
AsEnumerable preserves deferred execution and does not build an often useless intermediate list. On the other hand, when forced execution of a LINQ query is desired, ToList can be a way to do that. AsQueryable can be used to make an enumerable collection accept expressions in LINQ statements.
Unfortunately, I don't think there is a good "hard and fast" rule here. It depends a lot on how you expect the results to be used, and what the query itself is actually doing.
My initial thoughts are either any expression that may be iterated more than once or, to be safer in case potential iterations are not obvious, any expression whose result will never change.
In general, if you're going to use the result of a query more than once, it's always a good idea to store it via ToList()
or ToArray()
. This is especially true if you're LINQ query is an "expensive" one, as it prevents the expensive operation from running more than once.
Typically, if you're only going to enumerate the results, then I would leave it as IEnumerable<T>
. If you plan to store the results, or use the results more than once, then storing it in a collection can be beneficial.
The other place to watch for is if you return the results in a public API. While it's often nice to return IEnumerable<T>
, depending on the expected use case, you may want to consider using ToList()
to prevent the operation from being executed more than once.
As for whether to use ToList()
or ToArray()
, it really depends on how you'll use the results. The cost associated with each is nearly identical (ToList()
actually has slightly lower execution overhead if the input is not ICollection<T>
). Typically, I prefer ToList()
over ToArray()
unless I have a specific need or desire for an array.
ToList
calls List<T>(IEnumerable<T>)
constructor to create a List<T>
, while ToArrary
uses an internal class Buffer<T>
to grow the array.
If the source collection (IEnumerable<T>
) implements the ICollection
interface, the two methods use similar code logic to copy the data.
ICollection.CopyTo(array, 0);
Otherwise, ToList
will creates the List<T>
dynamically. While ToArray
copies the element one by one into a new array. If the array is full, the method doubles the array size to hold the data. Finally the method returns another array based on the source collection’s size.
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