Feel free to load your guns and take aim, but I want to understand why you shouldn't do this.
I have created a custom class designed to replace any instances of List (which I use to update XML objects behind them):
public class ListwAddRemove<T> : List<T> {
public event EventHandler<ListModifyEventArgs> OnAdd;
public event EventHandler<ListModifyEventArgs> OnRemove;
new public void Add(T o) {
base.Add(o);
if (OnAdd != null) {
OnAdd(this, new ListModifyEventArgs(o));
}
}
new public void Remove(T o) {
base.Remove(o);
if (OnRemove != null) {
OnRemove(this, new ListModifyEventArgs(o));
}
}
}
The idea is whenever I add or remove an item from this list my bound events will fire and I can deal with the XML behind automatically.
This works like a charm, so far so good.
But how do I handle a conversion between object.ToList() and my derived version?
A lot of people are saying you should derive from Collection instead... why?
You should derive from Collection<T>
because it's designed to allow you to override InsertItem
, and RemoveItem
to add custom behavior such as what you're doing (also SetItem
, to add custom behavior when changing an existing item).
It can therefore be used as an IList<T>
, and any insertion/removal will automatically use the customisation.
In your case, anyone who casts to IList<T>
or the base class List<T>
will bypass your custom Add/Remove functionality.
Collection<T>
also provides a constructor to wrap an existing list. You can expose this from your derived class to wrap a list generated by Enumerable<T>.ToList()
.
UPDATE
Whats the syntax to expose the constructor please?
Very simple:
public class ListwAddRemove<T> : Collection<T>
{
public ListwAddRemove<T>()
{
}
public ListwAddRemove<T>(IList<T> list) : base(list)
{
}
... implementation of overrides for InsertItem, SetItem, RemoveItem ...
}
Then use it as follows:
IList<SomeType> list = ....ToList();
ListwAddRemove<SomeType> myList = new ListwAddRemove<SomeType>(list);
For one,
void DoSomeAddingToList(List<int> list) {
list.Add(1);
}
var list = new ListwAddRemove<int>();
DoSomeAddingToList(list);
will not trigger the events. That might lead to strange effect, especially if you're not the only one using the class.
List<T>
defines a very specific behaviour for Add
and Remove
(since it's a concrete class), and users might rely on exactly this behaviour.
I think this is generally true for using a new
modifier, so this language feature should be used with caution, especially on public methods.
As others have mentioned, implementing IList<T>
(using delegation/aggregation) is probably the better choice.
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