我在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>
?
答案 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() {
}
};
};