2010-01-25 133 views
14

我在C++/CLI的自定义集合类中实现IEnumerable<T>时遇到问题。这里是代码的相关部分:在C++/CLI中实现IEnumerable <T>

using namespace System::Collections::Generic; 

ref class MyCollection : IEnumerable<MyClass^> 
{ 
public: 
    MyCollection() 
    { 
    } 

    virtual IEnumerator<MyClass^>^ GetEnumerator() 
    { 
     return nullptr; 
    } 
}; 

在编译时,这会导致以下错误:

错误C2392: “系统::收藏集::一般:: IEnumerator的 ^ MyCollection的:: GetEnumerator(void)': covariant返回类型不是受管理类型支持的 ,否则 'System :: Collections :: IEnumerator ^ System :: Collections :: IEnumerable :: GetEnumerator(void)' 将被覆盖错误C3766: 'MyCollection的' 必须为接口 方法 提供一种 执行 '系统::类别:: IEnumerator的 ^系统::类别::的IEnumerable ::的GetEnumerator(无效)'

这是有意义的,因为IEnumerable<T>来自IEnumerable。但是,我不知道如何解决这个编译错误。如果这是C#,我会隐式实现IEnumerable,但我不知道怎么做,在C++/CLI(如果这甚至有可能)是这样的:

class MyCollection : IEnumerable<MyClass> 
{ 
    public MyCollection() 
    { 
    } 

    public IEnumerator<MyClass> GetEnumerator() 
    { 
     return null; 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

如果我加IEnumerable::GetEnumerator()的实现,编译器抱怨两种方法只有返回类型不同(这也是有道理的)。

那么,如何在C++/CLI类中实现IEnumerable<T>

+0

相关http://stackoverflow.com/questions/3609967/c-cli-is-overloading-on-return-type-only-possible – 2011-02-09 11:36:25

回答

16

你必须提供一个明确的实施the non-generic GetEnumerator() method和包括非通用命名空间:

using namespace System::Collections; 

.... 

virtual IEnumerator^ EnumerableGetEnumerator() = IEnumerable::GetEnumerator 
{ 
    return GetEnumerator<MyClass^>(); 
} 

更新:正如评论所说,的GetEnumerator的明确的版本必须命名为不同的,以避免名称冲突,因此我将它命名为EnumerableGetEnumerator。

同样,在C#中,你会做这样的:

using System.Collections.Generic; 

public class MyCollection : IEnumerable<MyClass> 
{ 
    public MyCollection() 
    { 
    } 

    public IEnumerator<MyClass> GetEnumerator() 
    { 
     return null; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator<MyClass>(); 
    } 
} 
+0

仅仅实现的GetEnumerator()不工作。如果我这样做,我会得到一个编译器错误,指出重载的函数不能因返回类型而有所不同。 – Andy 2010-01-25 16:13:59

+0

更新我的问题,我将如何实现它在C# – Andy 2010-01-25 16:18:19

+0

猜猜我在这里有点快...现在它应该工作。如果不是的话,我会在脚下自杀。 – 2010-01-25 16:26:21

11

这不是很简单的。这是我的刺伤。填写“空白”。如果您同时使用集合和集合::通用名称空间,最大的问题之一就是模糊性。 C++/CLI真的很痛苦。

using namespace System; 
using namespace System::Collections; 

public ref struct Enumerable : public Generic::IEnumerable<String^> { 

public: 
    virtual Generic::IEnumerator<String^>^ GetEnumerator() sealed = Generic::IEnumerable<String^>::GetEnumerator { 
     return gcnew Enumerator(); 
    } 

    virtual IEnumerator^ GetEnumeratorBase() sealed = IEnumerable::GetEnumerator { 
     return GetEnumerator(); 
    } 

private: 
    ref struct TagEnumerator : public Generic::IEnumerator<String^> { 

    public: 
     property String^ Current { 
      virtual String^ get() { 
       throw gcnew NotImplementedException(); 
      } 
     }; 

     property Object^ CurrentBase { 
      virtual Object^ get() sealed = IEnumerator::Current::get { 
       throw gcnew NotImplementedException(); 
      } 
     }; 

     virtual bool MoveNext() { 
      throw gcnew NotImplementedException(); 
     } 

     virtual void Reset() { 
      throw gcnew NotImplementedException(); 
     } 

     virtual ~Enumerator() { 
     } 
    }; 
}; 
+0

谢谢。 “最大的问题之一是,如果你同时使用集合和集合::通用名称空间”,那么和Intellisense(TM)不断抱怨covariant回报的事实无关,即使编译成功后也是如此:) – sehe 2014-01-20 12:07:39

+0

不应该在CurrentBase的getter中有'return Current'? – Lars 2017-12-19 11:48:03

相关问题