How to implement custom collections in Visual C# (307484)



The information in this article applies to:

  • Microsoft Visual C# .NET (2002)
  • Microsoft Visual C# 2005

This article was previously published under Q307484
For a Microsoft Visual Basic .NET version of this article, see 306961.
For a Microsoft Visual C++ .NET version of this article, see 312514.

This article refers to the following Microsoft .NET Framework Class Library namespace:
  • System.Collection

IN THIS TASK

SUMMARY

This step-by-step article shows you how to implement a custom collection in Visual C# . The .NET Framework base class libraries offer a formal definition of a collection: the System.Collections.ICollection interface.

back to the top

Implementing the ICollection Interface in a Custom Class

The ICollection interface inherits from the IEnumerable interface. The ICollection interface defines a CopyTo method and three read-only properties: IsSynchronized, SyncRoot, and Count. ICollection inherits the GetEnumerator method from the IEnumerable interface. A custom collection class should implement the ICollection interface.

To implement the ICollection interface, follow these steps:
  1. In Visual C# .NET or Visual C# 2005, create a Windows application.
  2. In Solution Explorer, right-click the project name, point to Add, and then click Add Class to add a class module named CustomCollection.
  3. Add the following sample code to the beginning of the class module to import the System.Collection namespace:
    using System.Collections;
    					
  4. Replace any other code in the module with the following sample code:
     
    public class CustomCollection : ICollection
    {
    
        private int[] intArr = {1,5,9};
        private int Ct;
    
        public CustomCollection()
        {		
    	Ct=3;
        }
    }
    						
    For simplicity, the CustomCollection class holds an array with three integer items and a count variable.
  5. Implement the CopyTo method, which takes an integer array and an index as parameters. This method copies the items in a collection to the array starting at the index that is passed. To implement this method, paste the following code after the public CustomCollection constructor:
    void ICollection.CopyTo(Array myArr, int index)
    {
    			
        foreach (int i in intArr)
        {
    	myArr.SetValue(i,index);
    	index = index+1;
        }
    
    }
    					
  6. Implement the GetEnumerator method, which is inherited by the ICollection interface from IEnumerable. The GetEnumerator method returns an Enumerator object that can iterate through a collection. Paste the following sample code after the CopyTo method:
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new Enumerator(intArr);			  
    }
    
    					
  7. To implement the three read-only properties, paste the following code after the GetEnumerator method:
    // The IsSynchronized Boolean property returns True if the 
    // collection is designed to be thread safe; otherwise, it returns False.
    bool ICollection.IsSynchronized
    {
        get
        {
             return false;
        }
    }
    
    // The SyncRoot property returns an object, which is used for synchronizing 
    // the collection. This returns the instance of the object or returns the 
    // SyncRoot of other collections if the collection contains other collections.
    // 
    object ICollection.SyncRoot
    {
        get
        {
    	return this;
        }
    }
    
    // The Count read-only property returns the number 
    // of items in the collection.
    int ICollection.Count
    {
        get
        {
    	return Ct;
        }
    }
    					
back to the top

Implementing an Enumerator Object for the GetEnumerator Method

This section shows you how to create an Enumerator class that can iterate through CustomCollection.
  1. Paste the following sample code after the End Class statement in your class module:
    public class Enumerator : IEnumerator
    {
        private int[] intArr; 
        private int Cursor;
    }
    						
    Declare the intArr private integer array to hold the elements of the CustomCollection class when the GetEnumerator method is called. The Cursor field member holds the current position while enumerating.
  2. Add a constructor with intArr as a parameter and set the local intArr to this. Paste the following sample code after the member field's declaration:
    public Enumerator(int[] intarr)
    {
        this.intArr = intarr;
        Cursor = -1;
    
    }
  3. Implement the Reset and MoveNext methods. To do this, paste the following code after the constructor:
    void IEnumerator.Reset()
    {
        Cursor = -1;
    }
    bool IEnumerator.MoveNext()
    {
        if (Cursor < intArr.Length)
        Cursor++;
    
        return(!(Cursor == intArr.Length));
    }
    
    						
    Reset sets the cursor to -1 and MoveNext moves the cursor to the next element. MoveNext returns True if successful.
  4. Implement the Current read-only property that returns the item pointed by the cursor. If the cursor is -1, it generates an InvalidOperationException. Paste the following code after the MoveNext method:
    object IEnumerator.Current
    {
        get
        {
            if((Cursor < 0) || (Cursor == intArr.Length))
    	throw new InvalidOperationException();
    	return intArr[Cursor];
        }
    }
    					
back to the top

Using For Each to Iterate Through the Custom Collection

  1. In Form1.cs, on the Design tab, drag a button to the form.
  2. Double-click the button and add the following sample code to the Click event of the button:
        CustomCollection MyCol = new CustomCollection();
    		
        foreach (object MyObj in MyCol)
    	MessageBox.Show(MyObj.ToString());
    					
  3. Press F5 to run the application, and then click the button. Note that a message box displays the items in the custom collection.
How does this work? For Each calls the GetEnumerator method to create the Enumerator object and calls the MoveNext method to set the cursor to the first item. Then the Current property is accessed to get the item in MyObj. This is repeated until MoveNext returns False.

back to the top

Modification Type:MinorLast Reviewed:10/4/2006
Keywords:kbHOWTOmaster KB307484 kbAudDeveloper