在C ++ / CLI中实现IEnumerable <t> </t>

时间:2010-01-25 16:00:55

标签: .net c++-cli

我在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(无效)“:   协变返回类型不是   否则,托管类型支持   “系统::集合的IEnumerator ::   ^系统::收藏集:: IEnumerable的::的GetEnumerator(无效)”   将被覆盖的错误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>

2 个答案:

答案 0 :(得分:18)

您必须提供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>();
    }
}

答案 1 :(得分:12)

这不是很直截了当。这是我的抨击。填写“空白”。如果同时使用Collections和Collections :: Generic命名空间,最大的问题之一就是模糊不清。 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() {
        }
    };
};