I have the following scenario where I want to add some items to a List...
List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(...);
items.AddRange(addItems);
Using this code, no items are added to the list but if I add a .ToList() after then Linq statement then the items are added correctly. I guess this is due to deferred execution but I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
Can someone please clear up why this happens?
Accessing a List. A list can be accessed by an index, a for/foreach loop, and using LINQ queries. Indexes of a list start from zero. Pass an index in the square brackets to access individual list items, same as array.
Add---------It is used to add the item into the list one by one. AddRange-----------It is used to add the bulk of list item into the another list. Save this answer.
The AddRange method is called, with the list as its argument. The result is that the current elements of the list are added to the end of the list, duplicating all the elements.
I guess this is due to deferred execution but I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
It does. There is a short circuit for ICollection<T>
(which you wouldn't hit in this case), which would cause it to use ICollection<T>.CopyTo
instead of enumerating the items, but otherwise, it will enumerate the collection.
For a working example, try:
using System;
using System.Linq;
using System.Collections.Generic;
internal class Program
{
private static List<T> RunQuery<T>(IEnumerable<T> someCollection, Func<T, bool> predicate)
{
List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(predicate);
items.AddRange(addItems);
return items;
}
static void Main()
{
var values = Enumerable.Range(0, 1000);
List<int> results = RunQuery(values, i => i >= 500);
Console.WriteLine(results.Count);
Console.WriteLine("Press key to exit:");
Console.ReadKey();
}
}
This uses your exact code, and will print out 500 (the proper number of items in the List<T>
).
I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
I tried the below and AddRange(IEnumerable<T>)
does work
List<string> someCollection = new List<string>{"A", "B", "C"};
List<string> items = new List<string>();
IEnumerable<string> addItems = someCollection.Where(x => x != "");
items.AddRange(addItems);
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