Training
Module
Convert data types using casting and conversion techniques in C# - Training
Explore using C# techniques for casts and conversions.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
This article explains how to make type-safe collections for your own data types. Topics include:
The Microsoft Foundation Class Library provides predefined type-safe collections based on C++ templates. Because they are templates, these classes help provide type safety and ease of use without the type-casting and other extra work involved in using a nontemplate class for this purpose. The MFC sample COLLECT demonstrates the use of template-based collection classes in an MFC application. In general, use these classes any time you write new collections code.
Declare a variable of the collection class type. For example:
CList<int, int> m_intList;
Call the member functions of the collection object. For example:
m_intList.AddTail(100);
m_intList.RemoveAll();
If necessary, implement the helper functions and SerializeElements. For information on implementing these functions, see Implementing Helper Functions.
This example shows the declaration of a list of integers. The first parameter in step 1 is the type of data stored as elements of the list. The second parameter specifies how the data is to be passed to and returned from member functions of the collection class, such as Add
and GetAt
.
The template-based collection classes CArray
, CList
, and CMap
use five global helper functions that you can customize as needed for your derived collection class. For information on these helper functions, see Collection Class Helpers in the MFC Reference. Implementation of the serialization function is necessary for most uses of the template-based collection classes.
The CArray
, CList
, and CMap
classes call SerializeElements
to store collection elements to or read them from an archive.
The default implementation of the SerializeElements
helper function does a bitwise write from the objects to the archive, or a bitwise read from the archive to the objects, depending on whether the objects are being stored in or retrieved from the archive. Override SerializeElements
if this action is not appropriate.
If your collection stores objects derived from CObject
and you use the IMPLEMENT_SERIAL
macro in the implementation of the collection element class, you can take advantage of the serialization functionality built into CArchive
and CObject
:
CArray< CPerson, CPerson& > personArray;
template <> void AFXAPI SerializeElements <CPerson>(CArchive& ar,
CPerson* pNewPersons, INT_PTR nCount)
{
for (int i = 0; i < nCount; i++, pNewPersons++)
{
// Serialize each CPerson object
pNewPersons->Serialize(ar);
}
}
The overloaded insertion operators for CArchive
call CObject::Serialize
(or an override of that function) for each CPerson
object.
MFC also supports the collection classes introduced with MFC version 1.0. These classes are not based on templates. They can be used to contain data of the supported types CObject*
, UINT
, DWORD
, and CString
. You can use these predefined collections (such as CObList
) to hold collections of any objects derived from CObject
. MFC also provides other predefined collections to hold primitive types such as UINT
and void pointers (void*
). In general, however, it is often useful to define your own type-safe collections to hold objects of a more specific class and its derivatives. Note that doing so with the collection classes not based on templates is more work than using the template-based classes.
There are two ways to create type-safe collections with the nontemplate collections:
Use the nontemplate collections, with type casting if necessary. This is the easier approach.
Derive from and extend a nontemplate type-safe collection.
Use one of the nontemplate classes, such as CWordArray
, directly.
For example, you can create a CWordArray
and add any 32-bit values to it, then retrieve them. There is nothing more to do. You just use the predefined functionality.
You can also use a predefined collection, such as CObList
, to hold any objects derived from CObject
. A CObList
collection is defined to hold pointers to CObject
. When you retrieve an object from the list, you may have to cast the result to the proper type since the CObList
functions return pointers to CObject
. For example, if you store CPerson
objects in a CObList
collection, you have to cast a retrieved element to be a pointer to a CPerson
object. The following example uses a CObList
collection to hold CPerson
objects:
CPerson* p1 = new CPerson();
CObList myList;
myList.AddHead(p1); // No cast needed
CPerson* p2 = (CPerson*)myList.GetHead();
This technique of using a predefined collection type and casting as necessary may be adequate for many of your collection needs. If you need further functionality or more type safety, use a template-based class, or follow the next procedure.
Derive your own collection class from one of the predefined nontemplate classes.
When you derive your class, you can add type-safe wrapper functions to provide a type-safe interface to existing functions.
For example, if you derived a list from CObList
to hold CPerson
objects, you might add the wrapper functions AddHeadPerson
and GetHeadPerson
, as shown below.
class CPersonList : public CObList
{
public:
void AddHeadPerson(CPerson* person)
{
AddHead(person);
}
const CPerson* GetHeadPerson()
{
return (CPerson*)GetHead();
}
};
These wrapper functions provide a type-safe way to add and retrieve CPerson
objects from the derived list. You can see that for the GetHeadPerson
function, you are simply encapsulating the type casting.
You can also add new functionality by defining new functions that extend the capabilities of the collection rather than just wrapping existing functionality in type-safe wrappers. For example, the article Deleting All Objects in a CObject Collection describes a function to delete all the objects contained in a list. This function could be added to the derived class as a member function.
Training
Module
Convert data types using casting and conversion techniques in C# - Training
Explore using C# techniques for casts and conversions.