Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add an IEnumerable<T> to an existing ICollection<T>

Given an existing ICollection<T> instance (e.g. dest) what is the most efficient and readable way to add items from an IEnumerable<T>?

In my use case, I have some kind of utility method Collect(IEnumerable items) which returns a new ICollection with the elements from items, so I am doing it in the following way:

public static ICollection<T> Collect<T>(IEnumerable<T> items) where T:ICollection<T>
{
    ...
    ICollection<T> dest = Activator.CreateInstance<T>();
    items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });
    ...
    return dest;
}

Question: Is there any “better” way (more efficient or readable) of doing it?

UPDATE: I think the use of Aggregate() is quite fluent and not so inefficient as invoking ToList().ForEach(). But it does not look very readable. Since nobody else agrees with the use of Aggregate() I would like to read your reasons to NOT use Aggregate() for this purpose.

like image 276
Miguel Gamboa Avatar asked May 03 '16 09:05

Miguel Gamboa


People also ask

How can I add an item to a IEnumerable T collection?

What you can do is use the Add extension method to create a new IEnumerable<T> with the added value. var items = new string[]{"foo"}; var temp = items; items = items. Add("bar");

How do I add something to ICollection?

ICollection is an interface, you can't instantiate it directly. You'll need to instantiate a class that implements ICollection ; for example, List<T> . Also, the ICollection interface doesn't have an Add method -- you'll need something that implements IList or IList<T> for that.

Should I use IEnumerable or IList?

You use IEnumerable when you want to loop through the items in a collection. IList is when you want to add, remove, and access the list contents out of order.


2 Answers

Most efficient:

foreach(T item in itens) dest.Add(item)

Most readable (BUT inefficient because it is creating a throwaway list):

items.ToList().ForEach(dest.Add);

Less readable, but Not so inefficient:

items.Aggregate(dest, (acc, item) => { acc.Add(item); return acc; });
like image 188
Gaspium Avatar answered Sep 17 '22 09:09

Gaspium


Just use Enumerable.Concat:

IEnumerable<YourType> result = dest.Concat(items);

If you want a List<T> as result use ToList:

List<YourType> result = dest.Concat(items).ToList();
// perhaps:
dest = result;

If dest is actually already a list and you want to modify it use AddRange:

dest.AddRange(items);

Update:

if you have to add items to a ICollection<T> method argument you could use this extension:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> seq)
{
    List<T> list = collection as List<T>;
    if (list != null)
        list.AddRange(seq);
    else
    {
        foreach (T item in seq)
            collection.Add(item);
    }
}

// ...

public static void Foo<T>(ICollection<T> dest)
{
    IEnumerable<T> items = ... 
    dest.AddRange(items);
}
like image 45
Tim Schmelter Avatar answered Sep 20 '22 09:09

Tim Schmelter