Это правильный способ перебора Concurrentdictionary в С#

Я использую этот код только для примера. Предположим, у меня есть следующий класс Person.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace dictionaryDisplay
{
class Person
{
    public string FirstName { get; private set;}
    public string LastName { get; private set; }

    public Person(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;

    }

    public override string ToString()
    {
        return this.FirstName + " " + this.LastName;
    }
}

}

Основная программа

static void Main(string[] args)
    {
        ConcurrentDictionary<int, Person> personColl = new ConcurrentDictionary<int,   Person>();

        personColl.TryAdd(0, new Person("Dave","Howells"));
        personColl.TryAdd(1, new Person("Jastinder","Toor"));

        Person outPerson = null;
        personColl.TryRemove(0, out outPerson);


        //Is this safe to do?
        foreach (var display in personColl)
        {
            Console.WriteLine(display.Value);
        }





    }
  1. это безопасный способ перебора параллельного словаря? Если нет, то каков безопасный способ сделать это?

  2. Допустим, я хочу удалить объект Person из словаря. Я использую метод tryRemove, но что мне делать с объектом outPerson? в нем хранится удаленный из словаря Person. Что мне делать с объектом outPerson, чтобы полностью его очистить?


person Charles Whitfield    schedule 21.07.2013    source источник
comment
не пытаюсь придираться, но разве вы не пропустили использование статуса: using System.Collections.Concurrent; ?   -  person Trae Moore    schedule 22.07.2013
comment
Он есть, просто не включал.   -  person Charles Whitfield    schedule 22.07.2013


Ответы (2)


это безопасный способ перебора параллельного словаря? Если нет, то каков безопасный способ сделать это?

Да, это безопасно в том смысле, что оно не вызовет исключения. Если элементы добавляются или удаляются после начала итерации, они могут быть включены или не включены в итерацию. Из GetEnumerator документации:

Перечислитель, возвращенный из словаря, можно безопасно использовать одновременно с чтением и записью в словарь, однако он не представляет моментальный снимок словаря. Содержимое, отображаемое через перечислитель, может содержать изменения, внесенные в словарь после вызова GetEnumerator.

Следующий:

Я использую метод tryRemove, но что мне делать с объектом outPerson?

Все, что вы хотите с ним, включая ничего. Вы можете просто привести словарь к IDictionary<TKey, TValue> и вызвать Remove или просто использовать TryRemove и потом игнорировать переменную:

Person ignored;
dictionary.TryRemove(key, out ignored);

Или вы можете использовать функцию C# 7.0 Discards

dictionary.TryRemove(key, out _);

Не существует концепции "полной очистки [объекта]" - если у вас нет ссылок на него, он будет удален сборщиком мусора. Но в любом случае его больше нет в словаре (по крайней мере, через этот ключ). Если вы не используете переменную (ignored выше) где-либо еще в коде, это не остановит объект от сборки мусора.

person Jon Skeet    schedule 21.07.2013
comment
Я увидел этот вопрос и сразу понял, что будет ответ от Джона Скита... о чудо! - person davnicwil; 22.07.2013
comment
@ Jon Skeet - Будет ли это правильным способом разыграть его? IDictionary‹int,Person› removefromColl=(IDictionary‹int,Person›)personColl; - person Charles Whitfield; 22.07.2013
comment
@pawel Я откатился, так как это делает недействительным следующий абзац о переменной ignored. Также обратите внимание на это - person Christian Gollhardt; 29.07.2018

Взгляните на это статья.

TryRemove() was added to attempt atomic, safe removes.

    To safely attempt to remove a value we need to see if the key exists first, this checks for existence and removes under an atomic lock.

Поскольку TryRemove удалит элемент из коллекции, вам может понадобиться значение ключа.

Безопасно повторять его с помощью foreach. Вы не получите исключение.

person DarthVader    schedule 21.07.2013
comment
У OP действительно есть ключ. Что заставляет вас думать, что они этого не делают? И имейте в виду, что я использую этот код только в качестве примера — нет причин думать, что реальный код не будет использовать несколько потоков. - person Jon Skeet; 22.07.2013
comment
Я имел в виду значение того, чему соответствовал ключ. Должно быть, это что-то из американского английского. - person DarthVader; 22.07.2013
comment
Но точка зрения ОП в том, что им не нужно знать значение, соответствующее ключу... поэтому они не были уверены, что делать с параметром out. Во всяком случае, я так ответил... - person Jon Skeet; 22.07.2013