Преобразование std:: вектор<>:: итератор для интерфейса .NET на C ++ / CLI
-
01-07-2019 - |
Вопрос
Я создаю собственный класс C ++, который имеет следующие методы:
class Native
{
public:
class Local
{
std::string m_Str;
int m_Int;
};
typedef std::vector<Local> LocalVec;
typedef LocalVec::iterator LocalIter;
LocalIter BeginLocals();
LocalIter EndLocals();
private:
LocalVec m_Locals;
};
1) Каков ".NET-способ" представления такого же интерфейса?Единственный метод, возвращающий массив<>?Выполняет ли массив<> у generic есть итераторы, чтобы я мог реализовать BeginLocals() и EndLocals()?
2) Должен ли Local быть объявлен как ценностная структура в оболочке .NET?
Мне бы очень хотелось представить обернутый класс в стиле .NET, но я очень новичок в управляемом мире, и Google не может найти информацию такого типа...
Решение
Итераторы не совсем переводимы в ".net way", но они грубо заменяются на IEnumerable < T > и IEnumerator < T >.
Вместо того , чтобы
vector<int> a_vector;
vector<int>::iterator a_iterator;
for(int i= 0; i < 100; i++)
{
a_vector.push_back(i);
}
int total = 0;
a_iterator = a_vector.begin();
while( a_iterator != a_vector.end() ) {
total += *a_iterator;
a_iterator++;
}
вы бы увидели (в c #)
List<int> a_list = new List<int>();
for(int i=0; i < 100; i++)
{
a_list.Add(i);
}
int total = 0;
foreach( int item in a_list)
{
total += item;
}
Или более явно (не скрывая IEnumerator за синтаксическим сахаром foreach):
List<int> a_list = new List<int>();
for (int i = 0; i < 100; i++)
{
a_list.Add(i);
}
int total = 0;
IEnumerator<int> a_enumerator = a_list.GetEnumerator();
while (a_enumerator.MoveNext())
{
total += a_enumerator.Current;
}
Как вы можете видеть, foreach просто скрывает для вас перечислитель .net.
Так что на самом деле, ".net way" состоял бы в том, чтобы просто позволить людям создавать список< Локальные > товары для самих себя.Если вы действительно хотите управлять итерацией или сделать коллекцию немного более пользовательской, пусть ваша коллекция реализует IEnumerable< T > и/или ICollection< T > интерфейсы также.
Почти прямой перевод на c # был бы в значительной степени таким, как вы предполагали:
public class Native
{
public class Local
{
public string m_str;
public int m_int;
}
private List<Local> m_Locals = new List<Local>();
public List<Local> Locals
{
get{ return m_Locals;}
}
}
Тогда пользователь смог бы
foreach( Local item in someNative.Locals)
{
...
}
Другие советы
@Phillip - Спасибо, ваш ответ действительно помог мне двигаться в правильном направлении.
После просмотра вашего кода и еще немного чтения в книге Ниша C ++ / CLI в действии, Я думаю, что использование индексированного свойства, которое возвращает дескриптор отслеживания const локальному экземпляру в управляемой куче, вероятно, является лучшим подходом.В итоге я реализовал что-то похожее на следующее:
public ref class Managed
{
public:
ref class Local
{
String^ m_Str;
int m_Int;
};
property const Local^ Locals[int]
{
const Local^ get(int Index)
{
// error checking here...
return m_Locals[Index];
}
};
private:
List<Local^> m_Locals;
};