Let say I have
IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = list.Select(item => item * 10).Where(item => item < 20).ToList();
The question is are there two iterations or just one.
In other words, is that equivalent in performance to:
IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = new List<int>();
foreach(int item in list) {
int newItem = item * 10;
if(newItem < 20)
filtered.Add(newItem);
}
IEnumerable is the return type from an iterator. An iterator is a method that uses the yield return keywords. yield return is different from a normal return statement because, while it does return a value from the function, it doesn't “close the book” on that function.
IEnumerable is conceptually faster than List because of the deferred execution. Deferred execution makes IEnumerable faster because it only gets the data when needed. Contrary to Lists having the data in-memory all the time.
So if you working with only in-memory data collection IEnumerable is a good choice but if you want to query data collection which is connected with database `IQueryable is a better choice as it reduces network traffic and uses the power of SQL language.
IEnumerable is best to query data from in-memory collections like List, Array etc. IEnumerable doesn't support add or remove items from the list. Using IEnumerable we can find out the no of elements in the collection after iterating the collection. IEnumerable supports deferred execution.
There is a single iteration over the collection performed when you call the .ToArray
method so both should be equivalent. .Select
is a projection and .Where
is a filter, both expressed as expression trees on the original dataset.
Could be easily proven:
public class Foo: IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
yield return 1;
Console.WriteLine("we are at element 1");
yield return 2;
Console.WriteLine("we are at element 2");
yield return 3;
Console.WriteLine("we are at element 3");
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main()
{
var filtered = new Foo()
.Select(item => item * 10)
.Where(item => item < 20)
.ToList();
}
}
when run prints the following:
we are at element 1
we are at element 2
we are at element 3
In Linq to Objects WHERE and SELECT do not iterate over the enumerable. The calling code enumerates it when it does a foreach on the query or ToList or ToArray(), etc.
In Linq to SQL there is no iteration what so ever. When you do ToList or ToArray() the query is executed by database. Depending on the type of query db could look up indexes or do a table scan.
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