Collection<T> and CollectionBase
Collection<T> class is a customizable wrapper for List<T>.
As well as implementing IList<T> and IList, it defines four additional virtual meth-
ods and a protected property as follows:
public class Collection<T> :
IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
// ...
protected virtual void ClearItems();
protected virtual void InsertItem (int index, T item);
protected virtual void RemoveItem (int index);
protected virtual void SetItem (int index, T item);
protected IList<T> Items { get; }
}
The virtual methods provide the gateway by which you can “hook in” to change or
enhance the list’s normal behavior. The protected Items property allows the imple-
menter to directly access the “inner list”—this is used to make changes internally
without the virtual methods firing.
The virtual methods need not be overridden; they can be left alone until there’s a
requirement to alter the list’s default behavior. The following example demonstrates
the typical “skeleton” use of Collection<T>:
public class Animal
{
public string Name;
public int Popularity;
public Animal (string name, int popularity)
{
Name = name; Popularity = popularity;
}
}
public class AnimalCollection : Collection <Animal>
{
// AnimalCollection is already a fully functioning list of animals.
// No extra code is required.
}
public class Zoo // The class that will expose AnimalCollection.
{ // This would typically have additional members.
public readonly AnimalCollection Animals = new AnimalCollection();
}
class Program
{
static void Main()
{
Zoo zoo = new Zoo();
zoo.Animals.Add (new Animal ("Kangaroo", 10));
zoo.Animals.Add (new Animal ("Mr Sea Lion", 20));
foreach (Animal a in zoo.Animals) Console.WriteLine (a.Name);
}
}
As it stands, AnimalCollection is no more functional than a simple List<Animal>; its
role is to provide a base for future extension. To illustrate, we’ll now add a Zoo
property to Animal, so it can reference the Zoo in which it lives and override each of
the virtual methods in Collection<Animal> to maintain that property automatically:
public class Animal
{
public string Name;
public int Popularity;
public Zoo Zoo { get; internal set; }
public Animal(string name, int popularity)
{
Name = name; Popularity = popularity;
}
}
public class AnimalCollection : Collection <Animal>
{
Zoo zoo;
public AnimalCollection (Zoo zoo) { this.zoo = zoo; }
protected override void InsertItem (int index, Animal item)
{
base.InsertItem (index, item);
item.Zoo = zoo;
}
protected override void SetItem (int index, Animal item)
{
base.SetItem (index, item);
item.Zoo = zoo;
}
protected override void RemoveItem (int index)
{
this [index].Zoo = null;
base.RemoveItem (index);
}
protected override void ClearItems()
{
foreach (Animal a in this) a.Zoo = null;
base.ClearItems();
}
}
public class Zoo
{
public readonly AnimalCollection Animals;
public Zoo() { Animals = new AnimalCollection (this); }
}
Collection<T> also has a constructor accepting an existing IList<T>. Unlike with
other collection classes, the supplied list is proxied rather than copied, meaning that
subsequent changes will be reflected in the wrapping Collection<T> (although
without Collection<T>’s virtual methods firing). Conversely, changes made via the
Collection<T> will change the underlying list.
CollectionBase
CollectionBase is the nongeneric version of Collection<T> introduced in Framework
1.0. This provides most of the same features as Collection<T> but is clumsier to use.
Instead of the template methods InsertItem, RemoveItem SetItem, and ClearItem,
CollectionBase has “hook” methods that double the number of methods required:
OnInsert, OnInsertComplete, OnSet, OnSetComplete, OnRemove, OnRemoveComplete,
OnClear, and OnClearComplete. Because CollectionBase is nongeneric, you must also
implement typed methods when subclassing it—at a minimum, a typed indexer and
Add method.
No comments:
Post a Comment