AddThis Social Bookmark Button

Print

Implementing Custom Data Bindable Classes: IList

by James Still
09/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.

Programming .NET Components

Related Reading

Programming .NET Components
By Juval Löwy

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.

Pages: 1, 2, 3

Next Pagearrow