Implementing Custom Data Bindable Classes: IList
by James Still09/02/2003
It's no accident that DataSet, Array, TreeNodeCollection, and many other
collection classes all behave in a predictably similar fashion. Each of them derive from the
IList interface and each of them fully implement all of the methods defined by that
interface's contract. Thus, you can use them as data sources for iterative controls
like the DataGrid or list controls like DropDownList. You can enumerate
through all of the elements in the collection or access them individually by index position. In
this article, the third in a three-part series that picks up where the
previous two, on
CollectionBase and
IEnumerable left off, we're going to
implement the IList interface to create a custom collection class.
A Singly Linked List
Suppose that you have a tried and true data structure tucked away in your toolkit, a singly linked list that supports sequential access to its elements. You've relied on it many times over the years. It works great. Your class might even look something like this:
public class LinkedList
{
internal class Node
{
public Object item;
public Node next;
}
private Node head = null;
private int count = 0;
public int Count
{
get
{
return count;
}
}
public Object this[int index]
{
get
{
Node temp = head;
if (index > -1 && index < count)
{
for(int i = 0; i < index; ++i)
{
temp = temp.next;
}
return temp.item;
}
else
{
throw new IndexOutOfRangeException();
}
}
}
public void Insert(Object item)
{
if (head != null)
{
Node newNode = new Node();
newNode.item = item;
newNode.next = head;
head = newNode;
}
else
{
head = new Node();
head.item = item;
}
count++;
}
}
Why not use it in your next .NET project? You could, of course. When
someone from the front-end group calls your middle-tier object and gets back
this data structure it will work just fine, up to a point. But sooner or later one of them
will complain that he can't bind it to a DataGrid. Someone else will try to
use a foreach statement to iterate through the list, only to
discover
that your class doesn't support it. In the end, this singly linked list is
more trouble than it's worth because it fails to interact well with other
.NET components.
|
Related Reading Programming .NET Components |
The best way for your linked list class to play nice with other pieces of
software is for it to implement the IList interface. The IList interface is a
contract. It is a guarantee that when it comes to collections your code will behave in a standard way each
and every time. The compiler forces you to implement against its predefined
members--the methods and properties that describe what your collection will
do. Let's take a closer look at the IList interface.
The IList Interface
The IList interface derives from two other interfaces:
public interface IList : ICollection, IEnumerable
We covered the IEnumerable interface in the second article in
this series so I won't go into too much detail on it here. Altogether it has three
properties and seven methods:
interface IList {
bool IsFixedSize { get; }
bool IsReadOnly { get; }
object this[object key] { get; set; }
int Add(object value);
void Clear();
bool Contains(object value);
int IndexOf(object value);
void Insert(int index, object value);
void Remove(object value);
void RemoveAt(int index);
}
In order to be a .NET collection, all custom collection classes must implement the ICollection
interface. It has three properties and one method:
interface ICollection {
public bool IsSynchronized { get; }
public int Count { get; }
public object SyncRoot { get; }
public void CopyTo(Array array, int index);
}
IEnumerable is the standard interface for supporting the foreach statement
and an IEnumerator instance, both of which support enumeration through the collection. Since IList
derives from IEnumerable, you are required to implement it when you derive
your custom collection class from IList. It has a single method:
interface IEnumerable {
public IEnumerator GetEnumerator();
}
So, by implementing against the IList interface we support a standard method
for enumerating our list of elements, getting a single element by index
position, and inserting, removing, clearing, and counting them. Now that we
know what interface members we must implement, let's begin to port our singly linked list class over to a .NET collection
class.
IList
The first step in implementing IList is to derive it in our singly linked
list class:
public class LinkedList : IList {
internal class Node {
public Object Item;
public Node Next;
}
private Node head = null;
private int count = 0;
}
Here's a neat trick in Visual Studio: after you type "IList" wait for the
yellow tooltip to appear. It will prompt you to hit the Tab key if you want
Visual Studio to stub out the properties and methods of IList for you. Unless you enjoy
typing, hit the Tab key.


