Как вернуть копию оригинального Списка <T>из Func <T, TResult>? - PullRequest
1 голос
/ 05 марта 2009

Я обнаружил (сложным образом), что перечисляемая коллекция не может быть изменена в операторе "Foreach"

"Коллекция была изменена; операция перечисления может не выполняться."

Теперь, решение, которое я придумала, состоит в том, чтобы создать фиктивную коллекцию того же размера, которая содержит ключ словаря, и перечислить ее для изменения рассматриваемой коллекции.

    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();
    }

Над кодом работал нормально; Я занимался рефакторингом приведенного выше кода, чтобы использовать делегат Func для возврата копии ключей, как показано ниже

    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();
    }

В отличие от того, что я ожидал, getNodeIds не возвращает копию. Есть ли способ вернуть копию?

* РЕДАКТИРОВАТЬ : Временный результат до Ответ ДжаредПара

Похоже на ответ ДжаредПара, но он был более кратким, и я пошел с его ответом. Но вот схожий результат, которым я пришел поделиться.

    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();
    }

* РЕДАКТИРОВАТЬ : окончательный результат (уточнено)

_AuthenticatedNodes.Keys.ToList().ForEach(
    nodeId => _AuthenticatedNodes[nodeId] = false);

Ответы [ 3 ]

4 голосов
/ 05 марта 2009

Просто добавьте .ToList () в конец коллекции, и он автоматически вернет полную копию списка.

foreach (var nodeId in _AuthenticatedNodes.Keys.ToList())
    ...
1 голос
/ 05 марта 2009

После того, как вы измените класс Enumerable, ваш оригинальный перечислитель может стать недействительным, поэтому вам потребуется создать копию и внести в нее изменения.

1 голос
/ 05 марта 2009

Вместо использования foreach, вы можете использовать обычный для. Однако будьте осторожны при добавлении / удалении элементов, это меняет индексы элементов внутри коллекции.

...