var ints = new List< int >( new[ ] {
1,
2,
3,
4,
5
} );
var first = true;
foreach( var v in ints ) {
if ( first ) {
for ( long i = 0 ; i < int.MaxValue ; ++i ) { //<-- The thing I iterate
ints.Add( 1 );
ints.RemoveAt( ints.Count - 1 );
}
ints.Add( 6 );
ints.Add( 7 );
}
Console.WriteLine( v );
first = false;
}
Si comenta el for
bucle interno , arroja, obviamente es porque hicimos cambios en la colección.
Ahora, si lo descomentas, ¿por qué este bucle nos permite agregar esos dos elementos? Lleva un tiempo ejecutarlo como medio minuto (en CPU Pentium), pero no arroja, y lo curioso es que genera:
Era un poco de lo esperado, pero indica que podemos cambiar y en realidad cambia la colección. ¿Alguna idea de por qué ocurre este comportamiento?
c#
collections
LyingOnTheSky
fuente
fuente
int.MaxValue
iteraciones ...Respuestas:
El problema es que la forma de
List<T>
detectar modificaciones es manteniendo un campo de versión, de tipoint
, incrementándolo en cada modificación. Por lo tanto, si ha realizado exactamente un múltiplo de 2 32 modificaciones a la lista entre iteraciones, hará que esas modificaciones sean invisibles en lo que respecta a la detección. (Se desbordará a partirint.MaxValue
deint.MinValue
y, finalmente, volver a su valor inicial.)Si cambia prácticamente cualquier cosa sobre su código, agregue 1 o 3 valores en lugar de 2, o reduzca el número de iteraciones de su ciclo interno en 1, entonces arrojará una excepción como se esperaba.
(Este es un detalle de implementación en lugar de un comportamiento especificado, y es un detalle de implementación que se puede observar como un error en un caso muy raro. Sin embargo, sería muy inusual ver que causa un problema en un programa real).
fuente
_version
campo es unint
.InvalidOperationException
, que en realidad no siempre es cierto. Por supuesto, esto depende de la definición de "detalle de implementación".