2011-02-23 37 views
7

有沒有人有一個如何在C++/CLI中實現IEnumerable和IEnumerator的分步實例?或者,是否有人知道如何修復MS Connect中未在Visual Studio 2005中編譯的以下代碼?C++/CLI IEnumerable和IEnumerator實現

http://connect.microsoft.com/VisualStudio/feedback/details/101089/how-to-implement-ienumerable-t-and-ienumerable-c-cli

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; 
} 

編譯器不能找到枚舉的方法實現:

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 
+0

嘗試以防萬一。 (是的,我知道'ref struct'應該默認爲public)。或者使用顯式覆蓋符號,就像你爲'Current2 :: get'和'GetEnumerator2'所做的那樣,並讓編譯器告訴你爲什麼它不覆蓋。 – 2011-02-23 01:36:00

+0

您是否嘗試過Jamie所說的關於標記所有這些「虛擬」功能? – 2011-02-23 01:37:47

回答

14

這編譯爲我沒有一個單一的警告(在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; 
} 
+0

謝謝,這是偉大的工程! – Theo 2011-02-23 18:27:08

+0

對不起,我們將如何將它分成.h和.cpp文件? – Benjamin 2015-01-02 19:05:38

+0

@ginkner:我不會,我會像C++一樣爲模板使用僅頭部實現。然而,如果你堅持,你可以在類之外定義函數體,比如'generic bool MyArray :: enumerator :: MoveNext(){...}' – 2015-01-02 19:08:42

相關問題