Is it required or not to use ToList() after Select() in this code:
var names = someStorage.GetItems().Select(x => x.Name).ToList();
The Enumerable.ToList method will cause the population of data, if you do not call data wont be fetched and it will be a query.
The ToList(IEnumerable) method forces immediate
query evaluation and returns a List that contains the query
results. You can append this method to your query in order to obtain a
cached copy of the query results, MSDN.
It completely depends on what your code does subsequently. The ToList() method causes the query that you defined by using Select() to run immediately against the datastore. Without it, its execution would be delayed until you access the names variable for the first time.
The other aspect is that, if you don't use ToList(), the query will be run against the datastore each time you use the names variable - not just once as is the case with ToList(). So it also heavily depends on how often you use the names variable (If you use it only once (e.g. in a loop), then there is no difference, otherwise ToList() is much more efficient.
It depends on your assignment variable if you assigning to list then you need to convert.
If you do not call ToList it will be a IEnumerable<TSource> which is the enumerator, which supports a simple iteration over a collection of a specified type.
ToList converts the source sequence into a list. Some points to note:
The signature specifies List, not just IList. Of course it
could return a subclass of List, but there seems little point.
It uses immediate execution - nothing is deferred here
The parameter (source) musn't be null
It's optimized for the case when source implements ICollection
It always creates a new, independent list.
The last two points are worth a bit more discussion. Firstly, the optimization for ICollection isn't documented, but it makes a lot of sense:
List stores its data in an array internally
ICollection exposes a Count property so the List can create an
array of exactly the right size to start with
ICollection exposes a CopyTo method so that the List can copy
all the elements into the newly created array in bulk
Source to refer
Related
When I have a IEnumerable<SomeClass> from which I don't know wheter its a list or not (in terms of List<T>), and I have to enumerate that IEnumerable to make sure that I dont enumerate that enumerable twice (such as looping over it twice, or something like that).
Resharper warns me about possible multiple enumeration of IEnumerable - which is good, sometimes you forget it - and allows you to chose quickfixes:
Enumerate to array
Enumerate to list
When I chose Enumerate to list, resharper introduces a local variable, and assigns the IEnumerable the following way (example):
var enumeratedItems = items as IList<SomeClass> ?? items.ToList();
Now my question is:
Why doesn't it simply do items.ToList();?
What's the advantage of trying to cast to IList<SomeClass> first?
Maybe the IEnumerable is already a list, in this case calling ToList() will just create a new List from an exsiting one, so before doing it resharper suggest to try to cast it first to check if it is an IList or not and only in case it doesn't we will perform the ToList() operation that has some cost.
Why IEnumerable.ToList() won't work if like:
var _listReleases= new List<string>;
_listReleases.Add("C#")
_listReleases.Add("Javascript");
_listReleases.Add("Python");
IEnumerable sortedItems = _listReleases.OrderBy(x => x);
_listReleases.Clear();
_listReleases.AddRange(sortedItems); // won't work
_listReleases.AddRange(sortedItems.ToList()); // won't work
Note: _listRelealse will be null
It doesn't work because of this line:
_listReleases.Clear();
First of all, _listReleases is not null at this point. It's merely empty, which is a completely different thing.
But to explain why this doesn't work as you expect: the IEnumerable interface type does not actually allocate or reserve storage for anything. It represents an object that you can use with a foreach loop, and nothing more. It does not actually need to store the items in the collection itself.
Sometimes, an IEnumerable reference does have those items in the same object, but it doesn't have to. That's what's going on here. The OrderBy() extension method only creates an object that knows how to look at the original list and return the items in a specific order. But this does not have storage for those items. It still depends on it's original data source.
The best solution for this situation is to stop using the _listReleases variable at this point, and instead just use the sortedItems variable. As long the former is not garabage collected, the latter will do what you need. But if you really want the _listReleases variable, you can do it like this:
_listReleases = sortedItems.ToList();
Now back to IEnumerables. There are some nice benefits to this property of not requiring immediate storage of the items themselves, and merely abstracting the ability to iterate over a collection:
Lazy Evaluation - That the work required to produce those items is not done until called for (and often, that means it won't need to be done all all, greatly improving performance).
Composition - An IEnumerable object can be modified during a program to incorprate new sets of rules or operations into the final result. This reduces program complexity and improves maintainability by allowing you to break apart a complex set of sorting or filtering requirements into it's component parts. This also makes it much easier to build a program where these rules can be easily determined by the user at run time, instead of in advance by the programmer at compile time.
Memory Efficiency - An IEnumerable makes it possible to iterate collections of data from sources such as a database in ways that only need to keep the current record loaded into memory at any given time. This feature can also be used to create unbounded collections: sets of items that may stretch on to infinity. You can build an IEnumerable with the BigInteger type to calculate the next prime on to infinity, if asked for. Moreover, you could use that collection in a useful way without crashing or hanging the program by combining this with the composition feature, so the program will know when to stop.
LINQ is lazily evaluated. When you run this line:
IEnumerable sortedItems = _listReleases.OrderBy(x => x);
You aren't actually ordering the items right then and there. Instead you're building an enumerable that will, when enumerated, return the objects that are currently in _listReleases in order. So when you Clear() the list, it no longer has any items to order.
You need to force it to evaluate before you clear _listReleases. An easy way to do this is to add a ToList() call. Also, the type IEnumerable isn't compatible with AddRange won't accept it. You can just use var to implicitly type it to List<string>, which will work because List<T> : IEnumerable<T> (it implements the interface).
var sortedItems = _listReleases.OrderBy(x => x).ToList();
_listReleases.Clear();
_listReleases.AddRange(sortedItems);
You should also note that methods like ToList() are extension methods for IEnumerable<T>, not IEnumerable, so ((IEnumerable)something).ToList() won't work. Unlike, say, Java, Something<T> and Something are completely distinct types in C#.
I have a linq to entity query.
will Any() force linq execution (like ToList() does)?
There is very good MSDN article Classification of Standard Query Operators by Manner of Execution which describes all standard operators of LINQ. As you can see from table Any is executed immediately (as all operators which return single value). You can always refer this table if you have doubts about manner of operator execution.
Yes, and no. The any method will read items from the source right away, but it's not guaranteed to read all items.
The Any method will enumerate items from the source, but only as many as needed to determine the result.
Without any parameter, the Any method will only try to read the first item from the source.
With a parameter, the Any method will only read items from the source until it finds one that satisfies the condition. All items are only read from the source if no items satisfies the condition until the last item.
This is easy to discover: Any() returns a simple bool. Since a bool is always a bool, and not an IQueryable or IEnumerable (or any other type) that can have a custom implementation, we must conclude that Any() itself must calculate the boolean value to return.
The exception is of course if the Any() is used inside a subquery on a IQueryable, in which case the Linq provider will typically just analyse the presence of the call to Any() and convert it to corresponding SQL (for example).
Short question, short answer: Yes it will.
To find out if the any element of the list matches the given condition (or if there is any element at all) the list will have to be enumerated. As MSDN states:
This method does not return any one element of a collection. Instead, it determines whether the collection contains any elements.
The enumeration of source is stopped as soon as the result can be determined.
Deferred execution does not apply here, because this method delivers the result of an enumeration, not another IEnumerable.
I have a ILookup<TKey,TElement> lookup from which I fairly often get elements and iterate trough them using LINQ or foreach. I look up like this IEnumerable<TElement> results = lookup[key];.
Thus, results needs to be enumerated at least once every time I use lookup results (and even more if I'm iterating multiple times if I don't use .ToList() first).
Even though its not as "clean", wouldn't it be better (performance-wise) to use a Dictionary<TKey,List<TElement>>, so that all results from a key are only enumerated on construction of the dictionary? Just how taxing is ToList()?
ToLookup, like all the other ToXXX LINQ methods, uses immediate execution. The resulting object has no reference to the original source. It effectively does build a Dictionary<TKey, List<TElement>> - not those exact types, perhaps, but equivalent to it.
Note that there's a difference though, which may or may not be useful to you - the indexer for a lookup returns an empty sequence if you give it a key which doesn't exist, rather than throwing an exception. That can make life much easier if you want to be able to just index it by any key and iterate over the corresponding values.
Also note that although it's not explicitly documented, the implementation used for the value sequences does implement ICollection<T>, so calling the LINQ Count() method is O(1) - it doesn't need to iterate over all the elements.
See my Edulinq post on ToLookup for more details.
Assuming the implementation is System.Linq.Lookup (does ILookup have any other implementations?), the elements presented in lookup[key] are stored in an array of elements as a field of System.Linq.Lookup.Grouping. Repeatedly looking them up won't cause a re-iteration of source. Of course, rebuilding the Lookup will be more costly, but once built, the source is no longer accessed.
I have a dicionary of strings and dates
private readonly Dictionary<string, DateTime>
as a private member variable in a class
I have methods which recursively get the next and previous value in the dictionary given a particular key
e.g.
It takes the given key, does a database lookup, if that is null, it gets the next one and so on recursively. It does this both forward and backwards
I have used this to get the next one
Find next record in a set: LINQ
My question is can I simply add Reverse to the linq statement to do this backwards?
Obviously it will work but I am worried about the state it will leave my member variable list in
i.e. will it be reversed? or is a copy have made when doing the reverse?
thanks
Enumerable.Reverse does not mutate the sequence on which it is invoked.
As others have said, Enumerable.Reverse will not change the underlying sequence (except in the rare case where enumerating over the sequence will change it).
However, be warned that if you are using a List, you might end up calling List.Reverse, which DOES change the list.
List<int> list = /* initialize */;
IEnumerable<int> asEnumerable = list;
// these call List<int>.Reverse(), which changes the list
list.Reverse();
((List<int>)asEnumerable).Reverse();
// these call Enumerable.Reverse<int>(), which does not change the list, but returns a new IEnumerable<int>
asEnumerable.Reverse();
((IEnumerable<int>)list).Reverse();
((IList<int>)list).Reverse();
Sorry, I would have made this a comment on one of the other correct answers, but I wanted to include code.
None of the Linq methods, including Reverse, will alter the enumerable that is passed to them, UNLESS enumerating the enumerable causes alterations (you'd know if this were the case; few if any built-in Enumerable types have side effects to data access).
What reverse likely DOES do, since it requires knowledge of the cardinality of the collection, is to slurp the enumerable's elements into an array which it will iterate in reverse. A lot of oft-used Enumerable Linq methods, such as OrderBy, do this behind the scenes.