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;
}
Se você comentar o for
loop interno , ele lançará, obviamente é porque fizemos alterações na coleção.
Agora, se você descomentá-lo, por que esse loop nos permite adicionar esses dois itens? Demora um pouco para executá-lo como meio minuto (na CPU Pentium), mas ele não joga, e o engraçado é que ele produz:
Foi um pouco esperado, mas indica que podemos mudar e realmente muda a coleção. Alguma ideia de por que esse comportamento está ocorrendo?
c#
collections
LyingOnTheSky
fonte
fonte
int.MaxValue
iterações ...Respostas:
O problema é que a forma de
List<T>
detectar modificações é mantendo um campo de versão, do tipoint
, incrementando-o a cada modificação. Portanto, se você fez exatamente algum múltiplo de 2 32 modificações na lista entre as iterações, isso tornará essas modificações invisíveis no que diz respeito à detecção. (Ele irá estourar deint.MaxValue
paraint.MinValue
e, eventualmente, voltar ao seu valor inicial.)Se você alterar praticamente qualquer coisa em seu código - adicione 1 ou 3 valores em vez de 2, ou diminua o número de iterações de seu loop interno em 1, ele lançará uma exceção conforme o esperado.
(Este é um detalhe de implementação em vez de um comportamento especificado - e é um detalhe de implementação que pode ser observado como um bug em um caso muito raro. Seria muito incomum vê-lo causar um problema em um programa real, no entanto.)
fonte
_version
campo é umint
.InvalidOperationException
, o que nem sempre é verdade. Claro que isso depende da definição de "detalhes de implementação".