前一段时间,我asked about overriding IEnumerable in VC++。然后我接着另一个解决方案,所以我没有再访问它。现在,我需要它。但是,IEnumerable
现在需要IEnumerator
。
我在头文件中以空声明开始:
public ref class MyEnumerator : IEnumerator<MyClass^> {
};
当我尝试编译时,编译器会抱怨(应该):
Error 1 error C3766: 'Foo::MyEnumerator' must provide an implementation for the interface method 'System::Object ^System::Collections::IEnumerator::Current::get(void)'
正如我在其他帖子中所理解的那样,这是一种.net 1.x兼容方法。
所以,当我这样做时,我想我必须:
public ref class MyEnumerator : IEnumerator<MyClass^> {
public:
virtual System::Object Get1() = System::Collections::IEnumerator::Current::get {
return nullptr;
}
};
我现在得到:
Error 2 error C3671: 'Foo::Enumerator::Get1' : function does not override 'System::Collections::IEnumerator::Current::get'
我确实搜索了这个,但搜索关键字“visual c ++”“IEnumerator”和“visual c ++”“implement”“IEnumerator”并没有产生可用的搜索结果。不幸的是,我无法在VB.net或C#中实现这一部分,这将使这更容易,因为这是连接非托管第三方DLL的可怕部分,甚至连COM都不可见。
那么,我该如何做到这一点?或者我在哪里可以找到IEnumerator
的示例实现?
答案 0 :(得分:1)
请记住,实现自己的迭代器很少需要非常。您几乎总是依赖于.NET Framework实现的库存。但是当你实现自己的集合类时,你需要一个。不幸的是,你没有展示你的,我必须做一个。
假设您有一个存储MyClass对象的MyClassCollection并实现IEnumerable&lt;&gt;。要用作可索引集合,它需要一个Count属性来指示元素的数量,并需要一个索引器来从集合中返回一个MyClass元素:
using namespace System;
using namespace System::Collections::Generic;
public ref class MyClass {};
public ref class MyClassCollection : IEnumerable<MyClass^> {
internal:
int version;
public:
property int Count { // Needs implementation
int get();
}
property MyClass^ default[int] { // Needs implementation
MyClass^ get(int index);
}
virtual IEnumerator<MyClass^>^ GetEnumerator();
internal:
virtual System::Collections::IEnumerator^ GetEnumerator1() = System::Collections::IEnumerable::GetEnumerator{
return GetEnumerator();
}
};
我没有包含Add()和Remove()等成员。每当集合发生更改时递增version
成员,在枚举器中检测客户端代码是否继续迭代集合是有用的,即使它已经更改。
您的MyEnumerator类需要实现IEnumerator中的4个接口成员&lt;&gt;和一个实现IDisposable的析构函数。使用内部构造函数来传递集合对象:
public ref class MyEnumerator : IEnumerator<MyClass^> {
private:
MyClassCollection^ collection;
int index;
int version;
internal:
MyEnumerator(MyClassCollection^ source) : collection(source),
index(0), version(source->version) {}
public:
~MyEnumerator() {}
virtual bool MoveNext() {
if (index >= collection->Count) return false;
if (collection->version != version) collectionChanged();
index++;
return true;
}
virtual void Reset() {
index = 0;
}
virtual property MyClass ^ Current {
MyClass^ get() = IEnumerator<MyClass^>::Current::get {
if (collection->version != version) collectionChanged();
return collection[index];
}
}
internal:
virtual property System::Object ^ Current1 {
Object^ get() = System::Collections::IEnumerator::Current::get{
return Current;
}
}
private:
void collectionChanged() {
throw gcnew InvalidOperationException("Collection has changed");
}
};
除了常常笨拙的显式接口实现语法之外,这里看不多。析构函数很少需要做任何重要的事情,所以{}完全正常。请注意version
检查如何检测客户端代码继续迭代已更改的集合。 collectionChanged()方法有意保持独立,允许MoveNext和Current成员内联。我假设MyClassCollection索引器已经实现了边界检查,所以也没有在Current属性getter中检查它。
现在您可以编写GetEnumerator()方法:
IEnumerator<MyClass^>^ MyClassCollection::GetEnumerator() {
return gcnew MyEnumerator(this);
}