2010-04-26 17 views
5

Estoy portando una biblioteca de C++ a C#. La biblioteca anterior usa vectores de C++ y en C# estoy usando Diccionarios genéricos porque en realidad son una buena estructura de datos para lo que estoy haciendo (cada elemento tiene una ID, entonces solo uso usando TypeDictionary = Dictionary<String, Type>;). Ahora, en el código C# utilizo un bucle como éste¿Cómo saber si un enumerador ha llegado al final de la colección en C#?

TypeDictionary.Enumerator tdEnum = MyTypeDictionary.GetEnumerator(); 

while(tdEnum.MoveNext()) 
{ 
    Type element = typeElement.Current.Value; 

    // More code here 
} 

para iterar a través de los elementos de la colección. El problema es que en los casos particulares que necesito para comprobar si un determinado empadronador ha llegado al final de la colección, en C++ que habría hecho una comprobación de la siguiente manera:

if (tdEnum == MyTypeDictionary.end()) // More code here 

Pero simplemente no saben cómo manejar esta situación en C#, ¿alguna idea?

Gracias
Tommaso

Respuesta

3

Usted sabe que usted está al final de un iterador cuando MoveNext() vuelve false. De lo contrario, debe actualizar a una estructura de datos más descriptiva como IList<T>.

4

Tengo una clase de "iterador inteligente" en MiscUtil que puede serle útil. Le permite probar si actualmente está mirando el inicio o el final de la secuencia, y el índice dentro de la secuencia. Consulte usage page para obtener más información.

Por supuesto, en la mayoría de los casos puede simplemente hacer esto manualmente utilizando el resultado de MoveNext(), pero ocasionalmente la encapsulación adicional es útil.

Tenga en cuenta que, por necesidad, este iterador siempre habrá consumido un valor más de lo que arrojó, para saber si llegó o no al final. En la mayoría de los casos, eso no es un problema, pero ocasionalmente podría dar algunas experiencias extrañas al depurar.

+0

Gracias por su biblioteca, he marcado como favorito, pero por esta vez voy a ir con la solución rápida. :) – tunnuz

1

Si viene de C++, es posible que no tenga la sintaxis de C# actualizada. Quizás simplemente podría usar el constructo foreach para evitar la prueba todos juntos. El siguiente código se ejecutará una vez para cada elemento en su diccionario:

foreach (var element in MyTypeDictionary) 
{ 
    // More code here 
} 
2

Utilizando el patrón decorador para mantener un valor si el encuestador ha terminado es un enfoque válido. Como implementa IEnumerator, no encontrará dificultades para reemplazarlo en su código.

Aquí es una clase de prueba:

using System.Collections.Generic; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using MyDictionary = System.Collections.Generic.Dictionary<int, string>; 
using MyKeyValue = System.Collections.Generic.KeyValuePair<int, string>; 

namespace TestEnumerator 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestingMyEnumeradorPlus() 
     { 
      var itens = new MyDictionary() 
      { 
       { 1, "aaa" }, 
       { 2, "bbb" } 
      }; 
      var enumerator = new EnumeradorPlus<MyKeyValue>(itens.GetEnumerator()); 
      enumerator.MoveNext(); 
      Assert.IsFalse(enumerator.Ended); 
      enumerator.MoveNext(); 
      Assert.IsFalse(enumerator.Ended); 
      enumerator.MoveNext(); 
      Assert.IsTrue(enumerator.Ended); 
     } 
    } 

    public class EnumeradorPlus<T> : IEnumerator<T> 
    { 
     private IEnumerator<T> _internal; 
     private bool _hasEnded = false; 

     public EnumeradorPlus(IEnumerator<T> enumerator) 
     { 
      _internal = enumerator; 
     } 

     public T Current 
     { 
      get { return _internal.Current; } 
     } 

     public void Dispose() 
     { 
      _internal.Dispose(); 
     } 

     object System.Collections.IEnumerator.Current 
     { 
      get { return _internal.Current; } 
     } 

     public bool MoveNext() 
     { 
      bool moved = _internal.MoveNext(); 
      if (!moved) 
       _hasEnded = true; 
      return moved; 
     } 

     public void Reset() 
     { 
      _internal.Reset(); 
      _hasEnded = false; 
     } 

     public bool Ended 
     { 
      get { return _hasEnded; } 
     } 
    } 
} 
+0

Enumera ** d ** or? ¿error de tipografía? Debería ser Enumera ** t ** o – IlPADlI

+1

Sí, teniendo en cuenta que el ejemplo estaba escrito en inglés, es un error tipográfico (aunque en mi idioma nativo es la palabra para "enumerador"). Sin embargo, es el nombre de la clase, por lo que no afecta el resultado. – Fabio

Cuestiones relacionadas