代码之家  ›  专栏  ›  技术社区  ›  Andy

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

  •  14
  • Andy  · 技术社区  · 15 年前

    我在执行上有问题 IEnumerable<T> 在C++/CLI中的自定义集合类中。以下是守则的相关部分:

    using namespace System::Collections::Generic;
    
    ref class MyCollection : IEnumerable<MyClass^>
    {
    public:
        MyCollection()
        {
        }  
    
        virtual IEnumerator<MyClass^>^ GetEnumerator()
        {
            return nullptr;
        }
    };
    

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

    错误C2392: '系统::集合::通用::IEnumerator ^MyCollection::GetEnumerator(void)“”: 否则,在托管类型中受支持 ^系统::集合::IEnumerable::GetEnumerator(void)' 将被错误C3766覆盖: “MyCollection”必须提供 方法 '系统::集合::IEnumerator ^系统::集合::IEnumerable::GetEnumerator(void)'

    这是有道理的,因为 IEnumerable<T> 源于 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>

    2 回复  |  直到 10 年前
        1
  •  18
  •   Peter Lillevold Rene    9 年前

    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>();
        }
    }
    
        2
  •  12
  •   GotVino    14 年前

    这不是很简单。这是我的尝试。填空。最大的问题之一是,如果同时使用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() {
            }
        };
    };