Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does List.AddRange call List.Add?

Tags:

c#

.net

list

I have a custom class derived from List with an Add method that adds only if a certain condition is satisfied.

Do I also need to override* AddRange, or does AddRange simply call Add on each element of the given range?

*: Yes, new is hiding and not overriding in the context of C#.

like image 756
Superbest Avatar asked Feb 03 '13 16:02

Superbest


People also ask

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 is AddRange in list C#?

AddRange method in lists adds an entire collection of elements. Let us see an example − Firstly, set a list in C# and add elements − List<int> list = new List<int>(); list.Add(100); list.Add(200); list.Add(300); list.Add(400);

Is AddRange faster than foreach?

That means addrange is always faster than foreach . Does anyone know why? If you're worried about GC-sensitive perf (i.e. in a Unity game targeting mobile), AddRange will ToArray() the passed-in collection, which is an allocation. Bumping capacity and doing manual adds will probably be faster.

Is the AddRange feature used whenever adding multiple values to collection objects?

AddRange is used to add multiple elements. The add method inserts the item at the end of a collection. AddRange method is used to insert a set of records into a collection.


3 Answers

If you want to create custom collection. Don't derive it from List<T> but from Collection<T> or directly implement IList<T> or ICollection<T>. Indeed, the Add method in the List<T> class is not virtual.

Note: List<T>.AddRange uses Array.Copy.

UPDATE

When inheriting Collection you just have to override 2 methods!

public class MyCollection : Collection<string>
{
    private bool IsValidItem(string item)
    {
        return; // Your condition : true if valid; false, otherwise.
    }

    // This method will be called when you call MyCollection.Add or MyCollection.Insert
    protected override void InsertItem(int index, string item)
    {
        if(IsValidItem(item))
            base.InsertItem(index, item);
    }

    // This method will be called when you call MyCollection[index] = newItem
    protected override void SetItem(int index, string item)
    {
        if(IsValidItem(item))
            base.SetItem(index, item);
    }
}

If your items to validate are not string replace string in the code above by the correct type.

like image 147
Cédric Bignon Avatar answered Oct 02 '22 22:10

Cédric Bignon


Don't use hiding that changes the semantics of the method. That's really bad design.

Create a new class that implements IList<T>. The easiest way to do that is inheriting from Collection<T>. Collection<T> implements IList<T> and has four extension points in the form of protected virtual methods:

InsertItem
SetItem
RemoveItem
ClearItems

Since you only needs to validate items that get added and not those that get removed, you only need to override InsertItem and SetItem.

class MyCollection:Collection<T>
{
    private void ValidateItem(T item)
    {
       if(item is invalid)
         throw new ArgumentException("Item is invalid");
    }

    protected override InsertItem(int index, T item)
    {
        ValidateItem(item);
        base.InsertItem(index, item);
    }

    protected override SetItem(int index, T item)
    {
        ValidateItem(item);
        base.SetItem(index, item);
    }
}
like image 26
CodesInChaos Avatar answered Oct 02 '22 22:10

CodesInChaos


If you need a collection that behaves exactly like a List<T>, except for adding only valid objects, I wouldn't create a custom collection.

Use Extensions instead and call them AddIfValid(T value) and AddRangeIfValid(IEnumerable<T>) or whatever you like, as long as it's clear what the Extension is doing.

Here's an example:

public static void AddIfValid(this List<T> list, T value)
{
    if (/* check if value is valid here */)
        list.Add(value);
}

Once you have defined your Extension, use it like this:

myList.AddIfValid(myValue);
like image 21
Nolonar Avatar answered Oct 02 '22 21:10

Nolonar