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.
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");
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.
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.
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; });
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);
}
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