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

And*_*ndy 14 .net c++-cli

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

using namespace System::Collections::Generic;

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

    virtual IEnumerator<MyClass^>^ GetEnumerator()
    {
        return nullptr;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

错误C2392:'System :: Collections :: Generic :: IEnumerator ^ MyCollection :: GetEnumerator(void)':托管类型不支持协变返回类型,否则'System :: Collections :: IEnumerator ^ System :: Collections :: IEnumerable :: GetEnumerator(void)'将被覆盖错误C3766:'MyCollection'必须提供接口方法'System :: Collections :: IEnumerator ^ System :: Collections :: IEnumerable :: GetEnumerator(void)'的实现

这是有道理的,因为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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我确实添加了一个实现IEnumerable::GetEnumerator(),编译器会抱怨两种方法只有返回类型不同(这也是有意义的).

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

Pet*_*old 18

您必须提供非泛型GetEnumerator()方法的显式实现,并包含非泛型命名空间:

using namespace System::Collections;

....

virtual IEnumerator^ EnumerableGetEnumerator() = IEnumerable::GetEnumerator
{
    return GetEnumerator<MyClass^>();
}
Run Code Online (Sandbox Code Playgroud)

更新:如评论中所述,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>();
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 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() {
        }
    };
};
Run Code Online (Sandbox Code Playgroud)