Participei da seleção para uma empresa da Bélgica que desenvolve jogos para cassinos. Na primeira fase do processo foram feitas várias pequenas questões para verificar se o o candidato conhece os conceitos da linguagem. Quatro destas questões eram sobre listas ou listas e Linq. Abaixo uma delas, sobre a adição de novos elementos numa lista dentro de um laço foreach sobre a mesma lista:
Qual será a saída ao executar este código?
class Program {
static void Main() {
var ints = new List<int>(3) { 1, 2 };
foreach (int i in ints) {
ints.Add(i + 1);
}
Console.WriteLine("{0}", ints[2]);
}
}
a) A saída será 2 e a lista conterá 4 elementos.
b) A saída será 1 e a lista conterá 6 elementos.
c) A saída será 2 e a lista conterá 6 elementos.
d) Não irá compilar.
e) Haverá uma exceção do tipo “fora do intervalo” em tempo de execução.
f) Haverá uma exceção do tipo “operação inválida” em tempo de execução.
O programa é bem simples: cria uma lista com três posições e preenche as duas primeiras com 1 e 2. Depois disto, para cada elemento da lista adiciona um novo elemento, cujo valor é o elemento atual mais 1. Por fim, mostra o terceiro elemento da lista.
Ou seja:
A lista começa com os elementos 1 e 2. Na primeira iteração adiciona um novo elemento com valor 2 (1 + 1) e lista passa a ter três elementos (1, 2, 2). Na segunda interação adiciona o elemento 3 (2 + 1) e lista passa a ter 4 elementos (1, 2, 2, 3). Resultado, letra A: saída será 2 e a lista conterá 4 elementos. Certo? Não, errado. O sistema gera uma exceção em tempo de execução.
Mas por que ocorre uma exceção?
A exceção ocorre porque o código está tentando alterar a coleção dentro de um laço que percorre a própria coleção. Quando o programa é executado ele roda normalmente até inserir o primeiro novo elemento na lista, entretanto quando o cursor volta para o laço foreach ocorre o erro:
System.InvalidOperationException: ‘Collection was modified; enumeration operation may not execute.’
Ou seja, a coleção foi modifica e a operação sobre ela não pode ser executada. Resposta correta letra F: haverá uma exceção do tipo “operação inválida” em tempo de execução.
Execute o programa passo a passo usando o debug para ver o ponto exato onde a exceção é gerada
Este comportamento faz todo sentido, pois o laço foreach está preparado para percorrer toda a lista. Se a lista é modifica, seja por adição ou exclusão de elementos, como o compilador irá controlar quando o laço deve ser finalizado?
Mais uma dúvida….
Caso fosse possível adicionar novos elementos à lista dentro do foreach, surge uma nova questão: a lista foi declarada com tamanho três e iniciada com dois elementos, seria possível adicionar mais do que um elemento a ela ou neste caso teria uma exceção do tipo out of range (fora do intervalo)?
Isto pode ser testado modificando ligeiramente o código da questão, alterando o laço foreach para um laço for:
class Program {
static void Main() {
var ints = new List<int>(3) { 1, 2 };
for(int i = 1; i < 3; i++) {
ints.Add(i + 1);
}
Console.WriteLine("{0}", ints[2]);
}
}
No código acima dois novos elementos (2 e 3) são adicionados a lista, que passa a ter quatro elementos (1, 2, 2, 3). Nenhuma exceção é levantada, pois o tamanho da lista é alterado automaticamento de 3 para 4. O “3” usado no momento que a lista é instanciada em memória determina o tamanho inicial alocado e não o tamanho máximo.
| Origem da questão | ||
| País: Bélgica | Tipo: Conceitos | Assunto: List |
| Ramo de negócio da empresa: Games | Grau de Dificuldade: fácil | |