Pergunta

Quando enumerando uma coleção .NET, estados MSDN que:

Um enumerador permanece válido, desde que a coleção permanece inalterada. Se as mudanças são feitas para a recolha, tal como adicionar, modificar ou apagar elementos, o entrevistador é irrecuperavelmente invalidada e o seu comportamento é indefinido.

O que significa exatamente "irremediavelmente invalidado" significa?

Tome uma árvore binária, por exemplo, com referências tanto para baixo para crianças esquerda e direita, e também até pai. Em tal árvore uma, uma única referência a um único nó na árvore é suficiente para navegar através da árvore como você pode facilmente encontrar o próximo nó na árvore a partir dele.

Assim, com essa árvore, suponha que eu remover algum outro nó (presumivelmente, eu não remover o nó Atualmente estou sentado em), deve ainda invalidar o enumerador? Note que eu não estou falando de operação multi-threaded aqui, apenas um único segmento executando um loop, e modificar a coleção no interior do corpo do laço.

É este "direito" realmente, uma lei, que, mesmo se o enumerador poderia continuar, não deveria?

Foi útil?

Solução

É este "direito" realmente, uma lei, que, mesmo se o enumerador poderia continuar, não deveria?

Pessoalmente, eu acho que ter o seu lance recenseador, mesmo que teoricamente poderia continuar, é uma boa prática.

Muitas vezes, as pessoas, inadvertidamente, colocar o código que muda um interior coleção de um loop foreach. Sem isso, não pode estar jogando no caso específico o desenvolvedor está atualmente testando, mas uma condição de tempo de execução diferente poderia facilmente fazê-lo jogar.

Por sempre jogando, você está forçando o desenvolvedor para tratar o seu código o mesmo como coleções e enumerações do quadro, que eu acho que é uma coisa boa, uma vez que reduz o nível de surpresa quando se lida com a sua biblioteca.

Outras dicas

A implementação dos recenseadores padrão da coleção faz com que seja uma lei. Quando eles são criados, ele copia um inteiro privado "versão" do objeto de coleção. Modificando a coleção incrementa essa versão. Os métodos de iterador comparar a versão e quando há uma incompatibilidade ele lança. Não há maneira de contornar isso.

No entanto, há uma classe de coleção que permite modificar a coleção, enquanto eles são enumerados: Microsoft.VisualBasic.Collection. É necessário fazê-lo para ficar compatível com a classe VB6 Collection. Você pode querer dar uma olhada para ver como ele é feito. IIRC, ele mantém um WeakReference em todos os iteradores, em seguida, atualizar os iteradores quando a coleção é modificado. Isto não é à prova de idiotas é claro, a remoção de um elemento e adicionando-o novamente pode enumerar o mesmo objeto duas vezes. Também não é barato.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top