Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List.AddRange with IEnumerable<T> parameter not working?

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?

like image 643
John Avatar asked Jul 31 '12 23:07

John


People also ask

How to access a list element in c#?

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.

What is the difference between ADD and AddRange in C#?

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.

What does list AddRange do?

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.


2 Answers

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>).

like image 141
Reed Copsey Avatar answered Sep 23 '22 02:09

Reed Copsey


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);
like image 24
HatSoft Avatar answered Sep 27 '22 02:09

HatSoft