Does anyone have a working, step-by-step example of how to implement IEnumerable and IEnumerator in C++/CLI? Alternatively, does someone know how to fix the following code from MS Connect which does not compile in Visual Studio 2005?
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
bool MoveNext()
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
T get()
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() new sealed = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
void Reset() {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() new sealed = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}
The compiler is unable to find the enumerator method implementations:
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'bool System::Collections::IEnumerator::MoveNext(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'void System::Collections::IEnumerator::Reset(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'T System::Collections::Generic::IEnumerator<T>::Current::get(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>' must provide an implementation for the interface method 'System::Collections::Generic::IEnumerator<T> ^System::Collections::Generic::IEnumerable<T>::GetEnumerator(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 68
This compiles for me without a single warning (on VS2010):
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
virtual bool MoveNext() = IEnumerator<T>::MoveNext
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
virtual T get() = IEnumerator<T>::Current::get
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
virtual void Reset() = IEnumerator<T>::Reset {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
virtual IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}