locked
IEnumerable implementation fails - help RRS feed

  • Question

  • I am trying to implement IEnumerable on a List<> class member.  The sample code below illustrates what I am trying to do.  This code does not compile and generates the error messages shown below the sample code.  

    I do not seem to be able to find documentation the explains how this is to be done.  Would someone be kind enough to refer me to this documentation and/or provide sample code that illustrates how to correct the problem?  I've only been able to find one C++ reference to this topic (e.g. Overriding System::Generics::Collections::IEnumerable).

    Many thanks,

     

    Ian

     

     

     

    // testCLR.cpp : main project file.

    #include "stdafx.h"

    using namespace System;
    using namespace System::Collections::Generic;

    ref class MyList : public IEnumerable<Int32>
    {
    public:
     MyList() {
      _list = gcnew List<Int32>;
      for( int x = 0;  x < 10;  ++x ) {
       _list->Add( x );
      }
     }

     virtual IEnumerator<Int32>^ GetEnumerator() {
      return _list->GetEnumerator();
     }

    private:
     List<Int32> ^_list;
    };

    int main(array<System::String ^> ^args)
    {
     MyList ^myList = gcnew MyList;
     for each( Int32 i in myList ) {
      Console::WriteLine( i.ToString() );
     }
     
     return 0;
    }

     

     

     

     

     

     

     

    Compiler Error messages

    ------ Build started: Project: testCLR, Configuration: Debug Win32 ------
    Compiling...
    testCLR.cpp
    .\testCLR.cpp(18) : error C2392: 'System::Collections::Generic::IEnumerator<T> ^MyList::GetEnumerator(void)' : covariant returns types are not supported in managed types, otherwise 'System::Collections::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)' would be overridden
            with
            [
                T=int
            ]
            c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Collections::IEnumerable::GetEnumerator'
    .\testCLR.cpp(24) : error C3766: 'MyList' must provide an implementation for the interface method 'System::Collections::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)'
            c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Collections::IEnumerable::GetEnumerator'
    .\testCLR.cpp(8) : warning C4570: 'MyList' : is not explicitly declared as abstract but has abstract functions
            'System::Collections::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)' : is abstract
            c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Collections::IEnumerable::GetEnumerator'
    .\testCLR.cpp(28) : error C2259: 'MyList' : cannot instantiate abstract class
            due to following members:
            'System::Collections::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)' : is abstract
            c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Collections::IEnumerable::GetEnumerator'
    testCLR - 3 error(s), 1 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

     

    Saturday, March 17, 2007 5:53 AM

Answers

  • Try this:
    virtual IEnumerator<Int32>^ GetEnumerator()
    {
      return _list->GetEnumerator();
    }

    virtual System::Collections::IEnumerator^ IEnumerable_GetEnumerator()=
        System::Collections::IEnumerable::GetEnumerator
    {
      return GetEnumerator();
    }
    Saturday, March 17, 2007 7:33 AM
  • When you implement the IEnumerable<T> interface, you must also satisfy the requirements of the IEnumerable interface as well, since IEnumerable<T> derives from IEnumerable. Both interfaces have a GetEnumerator() method:

    virtual IEnumerable<T> System::Collections::Generic::GetEnumerator() and

    virtual IEnumerable System::Collections::GetEnumerator()

    The compliler will see these implementations as a redefinition differing only by return types. You can get around this limitation by renaming one of the methods (Name doesn't matter) and using C++/CLI(s) explicit override syntax.  The override could have been:

    virtual System::Collections::IEnumerator^ YourFunction()=System::Collections::IEnumerable::GetEnumerator {}

     

    Hope this helps.

     

     

     

    Monday, March 19, 2007 3:40 PM

All replies

  • Try this:
    virtual IEnumerator<Int32>^ GetEnumerator()
    {
      return _list->GetEnumerator();
    }

    virtual System::Collections::IEnumerator^ IEnumerable_GetEnumerator()=
        System::Collections::IEnumerable::GetEnumerator
    {
      return GetEnumerator();
    }
    Saturday, March 17, 2007 7:33 AM
  • Hello rjr,

    This works beautifully.  Many thanks.

    I put a breakpoint in this additional code and found it was never executed.  I just googled IEnumerable_GetEnumerator() and only came up with a handful of postings with example only in VB.   Would you be so good as to explain what your does does and why it was necessary? 

    A big thank you,

    Ian

    Saturday, March 17, 2007 2:57 PM
  • When you implement the IEnumerable<T> interface, you must also satisfy the requirements of the IEnumerable interface as well, since IEnumerable<T> derives from IEnumerable. Both interfaces have a GetEnumerator() method:

    virtual IEnumerable<T> System::Collections::Generic::GetEnumerator() and

    virtual IEnumerable System::Collections::GetEnumerator()

    The compliler will see these implementations as a redefinition differing only by return types. You can get around this limitation by renaming one of the methods (Name doesn't matter) and using C++/CLI(s) explicit override syntax.  The override could have been:

    virtual System::Collections::IEnumerator^ YourFunction()=System::Collections::IEnumerable::GetEnumerator {}

     

    Hope this helps.

     

     

     

    Monday, March 19, 2007 3:40 PM
  • This information proved extremely difficult to track down and I haven't been able to find it anywhere else.  The obscure compiler error message didn't help.  Thanks.

    Thursday, October 18, 2007 3:29 PM