Enumerators and Enumerator Interfaces

A frequent programming task is that of iterating through a sequence of items. The COM interfaces are no exception: there are places in several interfaces described in this specification where a client of some object needs to iterate through a sequence of items controlled by the object. COM supports such enumeration through the use of "enumerator objects." Enumerators cleanly separate the caller's desire to loop over a set of objects from the callee's knowledge of how to accomplish that function.

Enumerators are just a concept; there is no actual interface called IEnumerator or IEnum or the like. This is due to the fact that the function signatures in an enumerator interface must include the type of the things that the enumerator enumerates. As a consequence, separate interfaces exist for each kind of thing that can be enumerated. However, the difference in the type being enumerated is the only difference between each of these interfaces; they are all used in fundamentally the same way. In other words, they are "generic" over the element type. This document describes the semantics of enumerators using a generic interface IEnum and the C++ parameterized type syntax where ELT_T, which stands for ELemenT Type15. is representative of the type involved in the enumeration:


   
[
    object,
    uuid(<IID_IEnum <ELT_T>>),  // IID_IEnum<ELT_T>
    pointer_default(unique)
]
interface IEnum<ELT_T> : IUnknown
{
    HRESULT Next( [in] ULONG celt, [out] IUnknown **rgelt, [out] ULONG *pceltFetched );
    HRESULT Skip( [in] ULONG celt );
    HRESULT Reset( void );
    HRESULT Clone( [out] IEnum<ELT_T>**ppenum );
}

A typical use of an enumerator is the following.


//Somewhere there's a type called "String"
typedef char * String;

//Interface defined using template syntax
typedef IEnum<char *>   IEnumString;
...
interface IStringManager { 
   virtual IEnumString* EnumStrings(void) = 0;
   };
...
void SomeFunc(IStringManager * pStringMan)    {
   char *        psz;
   IEnumString * penum;
   penum=pStringMan->EnumStrings();
   while (S_OK==penum->Next(1, &psz, NULL))
      {
      //Do something with the string in psz and free it
      }
   penum->Release();
   return;
   }