实现 IEnumerable在 C++/CLI 中

发布于 2024-08-19 06:32:12 字数 1379 浏览 3 评论 0原文

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

using namespace System::Collections::Generic;

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

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

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

错误 C2392: '系统::集合::通用::IEnumerator ^MyCollection::GetEnumerator(void)': 协变返回类型不是 在托管类型中受支持,否则 '系统::集合::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)' 将被覆盖错误 C3766: “MyCollection”必须提供 接口的实现 方法 '系统::集合::IEnumerator ^System::Collections::IEnumerable::GetEnumerator(void)'

这是有道理的,因为 IEnumerable 派生自 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

I'm having problems implementing IEnumerable<T> in my custom collection class in C++/CLI. Here is the relevant part of the code:

using namespace System::Collections::Generic;

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

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

When compiled, this results in the following errors:

error C2392:
'System::Collections::Generic::IEnumerator
^MyCollection::GetEnumerator(void)':
covariant returns types are not
supported in managed types, otherwise
'System::Collections::IEnumerator
^System::Collections::IEnumerable::GetEnumerator(void)'
would be overridden error C3766:
'MyCollection' must provide an
implementation for the interface
method
'System::Collections::IEnumerator
^System::Collections::IEnumerable::GetEnumerator(void)'

This makes sense, since IEnumerable<T> derives from IEnumerable. However, I'm not sure how to fix this compile error. If this was C#, I would implicitly implement IEnumerable, however I'm not sure how to do that in C++/CLI (if that's even possible) like this:

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

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

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

If I do add an implementation of IEnumerable::GetEnumerator(), the compiler complains about two methods that differ only by return type (which also makes sense).

So, how do I implement IEnumerable<T> in a C++/CLI class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

┼── 2024-08-26 06:32:12

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

You must provide an explicit implementation of the non-generic GetEnumerator() method and include the non-generic namespace:

using namespace System::Collections;

....

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

Update: As mentioned in the comments, the explicit version of GetEnumerator must be named different to avoid name clash, thus I've named it EnumerableGetEnumerator.

Similarly, in C# you would have to do it like this:

using System.Collections.Generic;

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

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

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator<MyClass>();
    }
}
若无相欠,怎会相见 2024-08-26 06:32: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() {
        }
    };
};

It is not very straightforward. Here is my stab at it. Fill in the "blanks". One of the biggest issues is the ambiguity if you use both Collections and Collections::Generic namespace. C++/CLI is really a pain.

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() {
        }
    };
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文