Conversión de std::vector<>::iterator a interfaz .NET en C++/CLI
-
01-07-2019 - |
Pregunta
Estoy empaquetando una clase nativa de C++, que tiene los siguientes métodos:
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) ¿Cuál es la "forma .NET" de representar este mismo tipo de interfaz?¿Un método único que devuelve una matriz <>?¿El array<> genérico tiene iteradores para poder implementar BeginLocals() y EndLocals()?
2) ¿Debería declararse Local como estructura de valor en el contenedor .NET?
Realmente me gustaría representar la clase empaquetada con un sabor .NET, pero soy muy nuevo en el mundo administrado, y este tipo de información es frustrante para Google...
Solución
Los iteradores no se pueden traducir exactamente al "estilo .net", pero se reemplazan aproximadamente por IEnumerable < T > e IEnumerator < T >.
En vez de
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++;
}
verías (en 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;
}
O más explícitamente (sin ocultar el IEnumerator detrás del azúcar de sintaxis 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;
}
Como puede ver, foreach simplemente oculta el enumerador .net.
Entonces, en realidad, la "forma .net" sería simplemente permitir que las personas creen elementos de Lista <local> por sí mismos.Si desea controlar la iteración o hacer que la colección sea un poco más personalizada, haga que su colección implemente también las interfaces IEnumerable< T > y/o ICollection< T >.
Una traducción casi directa a C# sería más o menos lo que supuso:
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;}
}
}
Entonces un usuario podría
foreach( Local item in someNative.Locals)
{
...
}
Otros consejos
@Phillip: Gracias, tu respuesta realmente me ayudó a encaminarme en la dirección correcta.
Después de ver su código y leer un poco más en el libro de Nish C++/CLI en acción, creo que usar una propiedad indexada que devuelva un identificador de seguimiento constante a una instancia local en el montón administrado es probablemente el mejor enfoque.Terminé implementando algo similar a lo siguiente:
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;
};