How to implement custom collections in Visual C++ .NET or in Visual C++ 2005 (312514)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2002)
  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ 2005 Express Edition

This article was previously published under Q312514
For a Microsoft Visual C# .NET version of this article, see 307484.

For a Microsoft Visual Basic .NET version of this article, see 306961.

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

IN THIS TASK

SUMMARY

This article demonstrates how to implement custom collections in Visual C++ through the use of managed extensions. 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, you would take the following steps:
  1. Implement a CustomCollection class that is derived from ICollection. For simplicity, declare an integer array to hold integer items that are initialized with three integers. Also declare a Ct count variable that is set to "3", the size of the array.
  2. 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 and starts at the index that is passed.
  3. Implement the GetEnumerator method, which is inherited by ICollection from IEnumerable. The GetEnumerator method returns an object that implements the IEnumerable interface.
  4. Implement the read-only properties IsSynchronized, SyncRoot, and Count.
back to the top

Implementing an Enumerator Object for the GetEnumerator Method

  1. Implement an Enumerator class that is derived from IEnumerator to support enumeration of the CustomCollection class.
  2. 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 during enumeration.
  3. Add a constructor with intArr as a parameter to initialize the intArr member.
  4. Implement the Reset and MoveNext methods. (Reset sets the cursor to "-1", and MoveNext moves the cursor to the next element.) MoveNext returns True if enumeration is successful.
  5. Implement the read-only property Current, which returns the item that the cursor is pointing to. If the cursor is not pointing to a valid item, throw an InvalidOperationException.
back to the top

Iterating Through the Custom Collection

Visual C++ .NET does not support the foreach construct to iterate through the collection. But the following code does the equivalent:
    IEnumerator* ie=MyCol->GetEnumerator();
	while (ie->MoveNext())
	{   					
		Console::WriteLine(ie->Current->ToString());
	}
				
back to the top

Complete Code Sample

//compiler option: cl /clr  

#using <mscorlib.dll>
using namespace System;
using namespace System::Collections;
__gc class Enumerator : public IEnumerator
{
	int intArr  __gc []; 
	int Cursor;
public:
	Enumerator(int intarr __gc[])
	{   
		this->intArr = intarr;
		Cursor = -1;
	} 
	void IEnumerator::Reset()
	{
		Cursor = -1;
	}
	bool IEnumerator::MoveNext()
	{
		if (Cursor < intArr->Length)
			Cursor++;

		return(!(Cursor == intArr->Length));
	}
	Object* IEnumerator::get_Current()
	{
		if((Cursor < 0) || (Cursor == intArr->Length))
			throw new InvalidOperationException();
		return __box(intArr[Cursor]);
	}
};
__gc class CustomCollection : public ICollection
{

	int  intArr __gc[] ;
	int Ct;

public:
	CustomCollection()
	{	
        intArr =  new int __gc [3];
	intArr[0]=	1; 
	intArr[1]=	5;
	intArr[2]=	9;

	Ct=3;
	}
	void ICollection::CopyTo(Array* myArr, int index)
	{

		//foreach (int i in intArr)
		for(int i=0;i<intArr->Length;i++)
		{
			myArr->SetValue(__box(intArr[i]),index);
			index ++;
		}
	} 
	IEnumerator* IEnumerable::GetEnumerator()
	{
		return new Enumerator(intArr);			  
	}

	//The IsSynchronized Boolean property returns True if the 
	//collection is designed to be thread safe; otherwise, it returns False.
	bool ICollection::get_IsSynchronized()
	{ 
		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::get_SyncRoot()
	{
		return this;

	}

	//The Count read-only property returns the number 
	//of items in the collection.
	int ICollection::get_Count()
	{

		return Ct;

	} 
};

// This is the entry point for this application
int main()
{

	CustomCollection* MyCol = new CustomCollection();

	IEnumerator* ie=MyCol->GetEnumerator();
	while (ie->MoveNext())
	{   					
		Console::WriteLine(ie->Current->ToString());
	}
	return 0;
}
				
Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile this code sample. To do this, follow these steps:
  1. Click Project, and then click ProjectName Properties.

    Note ProjectName represents the name of the project.
  2. Expand Configuration Properties, and then click General.
  3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting on the right pane, click Apply, and then click OK.
For more information about the common language runtime support compiler options, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

back to the top

Modification Type:MajorLast Reviewed:1/12/2006
Keywords:kbHOWTOmaster kbManaged KB312514 kbAudDeveloper