Domanda

Ho scoperto (in modo duro) che una collezione che viene enumerata non può essere modificata in " Foreach " istruzione

  

" Collection è stata modificata; l'operazione di enumerazione non può essere eseguita. "

Ora, la soluzione che mi è venuta in mente è creare una collezione fittizia della stessa dimensione che contenga una chiave del dizionario ed enumerarla su di essa per modificare la raccolta in questione.

    private void InvalidateAuthenticatedNodes()
    {
        var dummy = new Dictionary<int, bool>(_AuthenticatedNodes.Count);
        foreach (var nodeId in _AuthenticatedNodes.Keys)
            dummy[nodeId] = false;

        foreach (var nodeId in dummy.Keys)
            _AuthenticatedNodes[nodeId] = false;

        ClearAuthenticatedDateTime();
    }

Il codice sopra ha funzionato bene; Stavo eseguendo il refactoring sopra il codice per utilizzare un delegato di Func per restituire una copia delle chiavi come segue

    private void InvalidateAuthenticatedNodes()
    {
        var getNodeIds = 
            new Func<Dictionary<int, bool>, IEnumerable<int>>(
                nodes => nodes.Select(node => node.Key));
        foreach (var nodeId in getNodeIds(_AuthenticatedNodes))
        {
            _AuthenticatedNodes[nodeId] = false;
        }

        ClearAuthenticatedDateTime();
    }

A differenza di quanto mi aspettassi, getNodeIds non restituisce una copia. Esiste un modo per restituire una copia?

* EDIT : risultato temporaneo prima di La risposta di JaredPar

Simile alla risposta di JaredPar ma la sua era più concisa e io ho seguito la sua risposta. Ma ecco il risultato simile che mi è venuto in mente di condividere.

    private void InvalidateAuthenticatedNodes()
    {
        var getNodeIds = 
            new Func<Dictionary<int, bool>, IEnumerable<int>>(nodes => 
                nodes.Select(node => node.Key));
        foreach (var nodeId in getNodeIds(_AuthenticatedNodes).ToList())
        {
            _AuthenticatedNodes[nodeId] = false;
        }

        ClearAuthenticatedDateTime();
    }

* EDIT : risultato finale (perfezionato)

_AuthenticatedNodes.Keys.ToList().ForEach(
    nodeId => _AuthenticatedNodes[nodeId] = false);
È stato utile?

Soluzione

Basta aggiungere un .ToList () alla fine della raccolta e restituirà automaticamente una copia completa dell'elenco.

foreach (var nodeId in _AuthenticatedNodes.Keys.ToList())
    ...

Altri suggerimenti

Invece di usare un foreach, puoi usare un normale per. Tuttavia, fai attenzione quando aggiungi / rimuovi elementi, cambia gli indici degli elementi all'interno della raccolta.

Una volta modificata una classe Enumerable, il tuo enumeratore originale potrebbe diventare non valido, quindi la necessità di creare una copia e apportare le modifiche lì.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top