WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Implementing Custom Data Bindable Classes: IList
Pages: 1, 2, 3

Let's implement the IList properties first. Two of them, IsReadOnly and IsFixedSize, are already done because the IDE has set them to return false. Since we want the list to grow and shrink with new values, this default setting is fine. But we do need to implement the Contains property, which should return true if any node in the list contains the value that is passed in as a parameter:




public bool Contains(object value) 
{
  bool containsNode = false;
  if (head != null) 
  {
    Node tempNode = head;
    if (tempNode.Item == value) 
    {
      containsNode 
        = true;
    }
    else 
    {
      for (int i = 0; i < count; ++i) 
      {
              
        tempNode = tempNode.Next;
              
        if (tempNode.Item == value) 
        {
                  
          containsNode = true;
              
        }
      }
    }
  }
  return containsNode;
}

We also have to implement an indexer so that elements can be accessed in the list by their index position:


	public object this[int index] 
{
  get 
  {
    Node temp = head;
    if (index > -1 && index < count) 
    {
      if (index != 
        0) 
      {
              
        for(int i = 0; i < index; ++i) 
        {
                  
          temp = temp.Next;
              
        }
      }
    }
    return temp.Item;
  }
  set 
  {
    Node temp = head;
    if (index > -1 && index < count) 
    {
      if (index != 
        0) 
      {
              
        for(int i = 0; i < index; ++i) 
        {
                  
          temp = temp.Next;
              
        }
      }
      temp.Item = 
        value;
    }
  }
}

That takes care of the properties for IList. Now let's implement its methods. The first method is Add, which accepts any object as its value and will insert a new node at the end of the list to store that value. It should return the index position of the new node:


public int Add(object value) 
{
  if (IsFixedSize) 
  {
    throw new NotSupportedException("List is a fixed size.");
  }

  if (head != null) 
  {
    Node tempNode = head;
    Node newNode = new Node();
    newNode.Item = value;

    // add Item to end of list
    for(int i = 0; i < count - 1; ++i) 
    {
      tempNode = tempNode.Next;
    }
    tempNode.Next = newNode;
  }
  else 
  {
    head = new Node();
    head.Item = value;
  }
  count++;
  return count;
}

The Clear method removes all nodes from the list:


	public void Clear() 
{
  if (IsReadOnly) 
  {
    throw new NotSupportedException("List is read-only.");
  }
  if (head != null) 
  {
    Node prevNode;
    Node tempNode = head;
    for (int i = 0; i < count; ++i) 
    {
      prevNode = tempNode;
      tempNode = tempNode.Next;
      prevNode = null;
    }
  }
}

The IndexOf method takes a value as a parameter and searches the list for that value. If found, it returns the index number for that node, otherwise it returns -1:


public int IndexOf(object value) 
{
    int idx = -1;
    Node temp = head;
    for(int i = 0; i < count; ++i) 
		{
        if (temp.Item == value) 
				{
            idx = i;
        }
    }
    return idx;
  }

The Insert method is similar to the Add method except that it can insert a new node anywhere in the list. That requires a little more work to implement:


	void System.Collections.IList.Insert(int index, object value) 
{
  if ((IsReadOnly) || (IsFixedSize)) 
  {
    throw new NotSupportedException("List is either " + 
      "read-only or a fixed size.");
  }

  if (index > -1 && index < count) 
  {
    // insert at position index
    if (head != null) 
    {
      Node currNode 
        = head;
      // get to 
      index position
        for (int i = 0; i == index; ++i) 
        {
          currNode = currNode.Next;
        }
      Node nextNode = currNode.Next;
      // create new node and assign value
      Node newNode  = new Node();
      newNode.Item  = value;
      // insert new node between curr and Next
      currNode.Next = newNode;
      newNode.Next = nextNode; 
    }
    else 
    {
      // insert in first position as the head
    head = new Node();
    head.Item = value;
    }
  }
  else 
  {
    throw new 
      ArgumentOutOfRangeException("Index is out of range.");
  }
  count++;
}

The last two methods in the IList interface are Remove and RemoveAt, which are similar in that both remove a node from the list. The difference is that Remove will search the list for a passed-in value and remove the first node that matches that value:


public void Remove(object value) 
{
  if (head != null) 
  {
    Node prevNode = head;
    Node tempNode = head;
  
    if (tempNode.Item == value) 
    {
      head = null;
    }
    else 
    {
      for (int i = 0; i < count; ++i) 
      {
        tempNode = tempNode.Next;
              
        if (tempNode.Item == value) 
        {
          // point previous node to Next node
          Node nextNode = tempNode.Next;
          prevNode.Next = nextNode;
          tempNode = null;
          count--;
          return;
        }
        else 
        {
          prevNode = tempNode;
        }
      }
    }
  }
  else 
  {
    throw new Exception("List is empty.");
  }
}

RemoveAt merely gets the node from the list at the location specified by the passed-in index position. In both cases, if the node to be removed is somewhere in the middle of the list, then we must link the previous node to the node after the one to be removed. If we didn't do that we'd break the chain and lose the integrity of our list:


public void RemoveAt(int index) 
{
  if ((IsReadOnly) || (IsFixedSize)) 
  {
    throw new NotSupportedException("List " +
      "is either read-only or a fixed size.");
  }

  if (index > -1 && index < count) 
  {
    if (head != null) 
    {
      // get to index position
      Node prevNode  = head;
      Node tempNode = head;
      if (index != 0) 
      {
        for (int i = 0; i < index; ++i) 
        {
          prevNode = tempNode;
          tempNode = tempNode.Next;
        }
        prevNode.Next = tempNode.Next;
        tempNode = null;
      }
      else 
      {
        head = tempNode.Next;
      }
      count--;
    }
    else 
    {
      throw new Exception("List is empty.");
    }
  }
  else 
  {
    throw new 
      ArgumentOutOfRangeException("Index is out of range.");
  }
}

Pages: 1, 2, 3

Next Pagearrow