Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

332
Vistas
Comportamiento extraño de Enumerator.MoveNext()

¿Alguien podría explicar por qué este código se ejecuta en bucle infinito? ¿Por qué MoveNext() devuelve true siempre?

 var x = new { TempList = new List<int> { 1, 3, 6, 9 }.GetEnumerator() }; while (x.TempList.MoveNext()) { Console.WriteLine("Hello World"); }
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

List<T>.GetEnumerator() devuelve un tipo de valor mutable ( List<T>.Enumerator ). Está almacenando ese valor en el tipo anónimo.

Ahora, echemos un vistazo a lo que esto hace:

 while (x.TempList.MoveNext()) { // Ignore this }

Eso es equivalente a:

 while (true) { var tmp = x.TempList; var result = tmp.MoveNext(); if (!result) { break; } // Original loop body }

Ahora tenga en cuenta a lo que llamamos MoveNext() : la copia del valor que está en el tipo anónimo. En realidad, no puede cambiar el valor en el tipo anónimo: todo lo que tiene es una propiedad a la que puede llamar, que le dará una copia del valor.

Si cambias el código a:

 var x = new { TempList = (IEnumerable<int>) new List<int> { 1, 3, 6, 9 }.GetEnumerator() };

... entonces terminará obteniendo una referencia en el tipo anónimo. Una referencia a un cuadro que contiene el valor mutable. Cuando llamas a MoveNext() en esa referencia, el valor dentro del cuadro se mutará, por lo que hará lo que quieras.

Para un análisis de una situación muy similar (nuevamente usando List<T>.GetEnumerator() ), consulte mi publicación de blog de 2010 "¡Itera, maldita sea!" .

over 4 years ago · Santiago Trujillo Denunciar

0

Si bien la construcción foreach en C# y el bucle For Each en VB.NET a menudo se usan con tipos que implementan IEnumerable<T> , aceptarán cualquier tipo que incluya un método GetEnumerator cuyo tipo de retorno proporcione una función MoveNext y una propiedad Current adecuadas. Hacer que GetEnumerator devuelva un tipo de valor permitirá en muchos casos que foreach se implemente de manera más eficiente de lo que sería posible si devolviera IEnumerator<T> .

Desafortunadamente, debido a que no existe ningún medio por el cual un tipo pueda proporcionar un enumerador de tipo de valor cuando se invoca desde foreach sin proporcionar también uno cuando se invoca mediante una llamada al método GetEnumerator , los autores de List<T> enfrentaron una ligera compensación de rendimiento versus semántica. En ese momento, debido a que C# no admitía la inferencia de tipo variable, cualquier código que usara el valor devuelto por List<T>.GetEnumerator tendría que declarar una variable de tipo IEnumerator<T> o List<T>.Enumerator . El código que usa el primer tipo se comportaría como si List<T>.Enumerator fuera un tipo de referencia, y se podría suponer que un programador que usa el último se daría cuenta de que era un tipo de estructura. Sin embargo, cuando C# agregó la inferencia de tipos, esa suposición dejó de ser válida. El código podría fácilmente terminar usando el tipo List<T>.Enumerator sin que el programador sepa de la existencia de ese tipo.

Si C# alguna vez definiera un atributo de método de estructura que podría usarse para etiquetar métodos que no deberían invocarse en estructuras de solo lectura, y si List<T>.Enumerator lo usara, un código como el suyo podría generar correctamente un error de tiempo de compilación en la llamada a MoveNext en lugar de generar un comportamiento falso. Sin embargo, no conozco ningún plan particular para agregar dicho atributo.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda