[c#] AddRange to a Collection

A coworker asked me today how to add a range to a collection. He has a class that inherits from Collection<T>. There's a get-only property of that type that already contains some items. He wants to add the items in another collection to the property collection. How can he do so in a C#3-friendly fashion? (Note the constraint about the get-only property, which prevents solutions like doing Union and reassigning.)

Sure, a foreach with Property. Add will work. But a List<T>-style AddRange would be far more elegant.

It's easy enough to write an extension method:

public static class CollectionHelpers
{
    public static void AddRange<T>(this ICollection<T> destination,
                                   IEnumerable<T> source)
    {
        foreach (T item in source)
        {
            destination.Add(item);
        }
    }
}

But I have the feeling I'm reinventing the wheel. I didn't find anything similar in System.Linq or morelinq.

Bad design? Just Call Add? Missing the obvious?

This question is related to c# collections c#-3.0 extension-methods

The answer is


You could add your IEnumerable range to a list then set the ICollection = to the list.

        IEnumerable<T> source;

        List<item> list = new List<item>();
        list.AddRange(source);

        ICollection<item> destination = list;

Since .NET4.5 if you want one-liner you can use System.Collections.Generic ForEach.

source.ForEach(o => destination.Add(o));

or even shorter as

source.ForEach(destination.Add);

Performance-wise it's the same as for each loop (syntactic sugar).

Also don't try assigning it like

var x = source.ForEach(destination.Add) 

cause ForEach is void.

Edit: Copied from comments, Lipert's opinion on ForEach


The C5 Generic Collections Library classes all support the AddRange method. C5 has a much more robust interface that actually exposes all of the features of its underlying implementations and is interface-compatible with the System.Collections.Generic ICollection and IList interfaces, meaning that C5's collections can be easily substituted as the underlying implementation.


Or you can just make an ICollection extension like this:

 public static ICollection<T> AddRange<T>(this ICollection<T> @this, IEnumerable<T> items)
    {
        foreach(var item in items)
        {
            @this.Add(item);
        }

        return @this;
    }

Using it would be just like using it on a list:

collectionA.AddRange(IEnumerable<object> items);

Remember that each Add will check the capacity of the collection and resize it whenever necessary (slower). With AddRange, the collection will be set the capacity and then added the items (faster). This extension method will be extremely slow, but will work.


Try casting to List in the extension method before running the loop. That way you can take advantage of the performance of List.AddRange.

public static void AddRange<T>(this ICollection<T> destination,
                               IEnumerable<T> source)
{
    List<T> list = destination as List<T>;

    if (list != null)
    {
        list.AddRange(source);
    }
    else
    {
        foreach (T item in source)
        {
            destination.Add(item);
        }
    }
}

Here is a bit more advanced/production-ready version:

    public static class CollectionExtensions
    {
        public static TCol AddRange<TCol, TItem>(this TCol destination, IEnumerable<TItem> source)
            where TCol : ICollection<TItem>
        {
            if(destination == null) throw new ArgumentNullException(nameof(destination));
            if(source == null) throw new ArgumentNullException(nameof(source));

            // don't cast to IList to prevent recursion
            if (destination is List<TItem> list)
            {
                list.AddRange(source);
                return destination;
            }

            foreach (var item in source)
            {
                destination.Add(item);
            }

            return destination;
        }
    }

Agree with some guys above and Lipert's opinion. In my case, it's quite often to do like this:

ICollection<int> A;
var B = new List<int> {1,2,3,4,5};
B.ForEach(A.Add);

To have an extension method for such operation a bit redundant in my view.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to collections

Kotlin's List missing "add", "remove", Map missing "put", etc? How to unset (remove) a collection element after fetching it? How can I get a List from some class properties with Java 8 Stream? Java 8 stream map to list of keys sorted by values How to convert String into Hashmap in java How can I turn a List of Lists into a List in Java 8? MongoDB Show all contents from all collections Get nth character of a string in Swift programming language Java 8 Distinct by property Is there a typescript List<> and/or Map<> class/library?

Examples related to c#-3.0

how to check if string value is in the Enum list? Label word wrapping how to insert datetime into the SQL Database table? How to fit Windows Form to any screen resolution? C# adding a character in a string How to dynamic new Anonymous Class? How to get index using LINQ? System.Drawing.Image to stream C# AddRange to a Collection Metadata file '.dll' could not be found

Examples related to extension-methods

The operation cannot be completed because the DbContext has been disposed error Extension methods must be defined in a non-generic static class Java equivalent to C# extension methods Razor HtmlHelper Extensions (or other namespaces for views) Not Found Mocking Extension Methods with Moq AddRange to a Collection Distinct() with lambda? Convert string[] to int[] in one line of code using LINQ How do I extend a class with c# extension methods? Static extension methods