¿Es esta la forma correcta de iterar sobre Concurrentdictionary en C#


Solo estoy usando este código para un ejemplo. Supongamos que tengo la siguiente clase de Persona.

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

}

Programa principal

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. ¿Es esta la forma segura de iterar sobre un diccionario concurrente? Si no, ¿cuál es la forma segura de hacerlo?

  2. Digamos que quiero eliminar un objeto Person del diccionario. Uso el método tryRemove, pero ¿qué hago con el objeto outPerson? la Persona eliminada del diccionario se almacena en él. Qué hacer ¿Lo hago con el objeto outPerson para borrarlo completamente?

Author: Charles Whitfield, 2013-07-22

2 answers

¿Es esta la forma segura de iterar sobre un diccionario concurrente? Si no, ¿cuál es la forma segura de hacerlo?

Sí, es seguro que no lanzará una excepción. Si los elementos se agregan o eliminan después de comenzar la iteración, pueden o no incluirse en la iteración. Desde el GetEnumerator documentación:

El enumerador devuelto desde el diccionario es seguro de usar simultáneamente con lee y escribe en el diccionario, sin embargo no representa una instantánea del momento en el tiempo del diccionario. Los contenidos expuestos a través del enumerador pueden contener modificaciones hechas al diccionario después de que GetEnumerator fue llamado.

Siguiente:

Uso el método tryRemove, pero ¿qué hago con el objeto outPerson?

Lo que quieras con él, incluyendo nada. Usted podría simplemente emitir el diccionario IDictionary<TKey, TValue> y llamar a Remove, o TryRemove e ignorar la variable después:

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

Hay no hay concepto de "limpiar [el objeto] completamente" - si no tiene ninguna referencia a él, será basura recolectada. Pero de cualquier manera, ya no está en el diccionario (al menos a través de esa clave). Si no utiliza la variable (ignored anterior) en ningún otro lugar del código, no impedirá que el objeto sea recogido como basura.

 39
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-29 05:43:46

Echa un vistazo a este artículo.

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.

Dado que TryRemove eliminará el elemento de la colección, es posible que necesite el valor de la clave.

Es seguro iterar con foreach. No tendrás una excepción.

 2
Author: DarthVader,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-21 20:22:48