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