Реализация IEnumerable <T>в C ++ / CLI - PullRequest
14 голосов
/ 25 января 2010

У меня проблемы с реализацией IEnumerable<T> в моем собственном классе коллекции в C ++ / CLI. Вот соответствующая часть кода:

using namespace System::Collections::Generic;

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

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

При компиляции это приводит к следующим ошибкам:

ошибка C2392: «System :: Подборки :: Общий :: IEnumerator ^ MyCollection :: GetEnumerator (аннулируются) ': ковариантные типы возвратов не поддерживается в управляемых типах, в противном случае «System :: Коллекция :: IEnumerator ^ Система :: Подборки :: IEnumerable :: GetEnumerator (аннулируются)» будет переопределена ошибка C3766: «MyCollection» должен предоставить реализация для интерфейса метод «System :: Коллекция :: 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(), компилятор пожалуется на два метода, которые отличаются только типом возвращаемого значения (что также имеет смысл).

Итак, как мне реализовать IEnumerable<T> в классе C ++ / CLI?

Ответы [ 2 ]

18 голосов
/ 25 января 2010

Вы должны предоставить явную реализацию неуниверсального метода GetEnumerator () и включить неуниверсальное пространство имен:

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>();
    }
}
12 голосов
/ 27 июля 2010

Это не очень просто.Вот мой удар в этом.Заполнить бланки".Одна из самых больших проблем - это двусмысленность, если вы используете и Collections, и Collections :: Generic namespace.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() {
        }
    };
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...