2013-07-21 27 views
22

Sto solo usando questo codice per un esempio. Supponiamo che abbia la seguente classe Person.È il modo corretto di scorrere su Concurrentdictionary in C#

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

}

Programma principale

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. è questo il modo sicuro di iterare su un dizionario concomitante? In caso contrario, qual è il modo sicuro per farlo?

  2. Diciamo che voglio rimuovere un oggetto Persona dal dizionario. Io uso il metodo tryRemove, ma cosa faccio con l'oggetto outPerson? la Persona rimossa dal dizionario è memorizzata in essa. Cosa devo fare con l'oggetto outPerson per cancellarlo completamente?

+1

non tentare di selezionare nit, ma non ti manca l'uso di statment: 'using System.Collections.Concurrent;'? –

+2

È lì, non l'ho incluso. –

risposta

32

è questo il modo sicuro di iterare su un dizionario concomitante? In caso contrario, qual è il modo sicuro per farlo?

Sì, è sicuro in quanto non farà eccezione. Se gli elementi vengono aggiunti o rimossi dopo l'avvio della iterazione, possono essere inclusi o meno nell'iterazione. Dal GetEnumerator documentation:

L'enumeratore restituito dal dizionario è sicuro da usare in concomitanza con letture e scritture al dizionario, tuttavia non rappresenta un'istantanea momento-in-time del dizionario. I contenuti esposti tramite l'enumeratore possono contenere modifiche apportate al dizionario dopo che è stato chiamato GetEnumerator.

successivo:

Io uso il metodo tryRemove, ma cosa devo fare con l'oggetto outPerson?

Qualsiasi cosa tu voglia con esso, compreso niente. Si potrebbe semplicemente lanciare il dizionario per IDictionary<TKey, TValue> e chiamare Remove, o semplicemente usare TryRemove e ignorare la variabile in seguito:

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

Non c'è alcun concetto di "compensazione [l'oggetto] completamente" - se non hai tutti i riferimenti ad esso, saranno raccolti i rifiuti. Ma in entrambi i casi, non è più nel dizionario (almeno tramite quella chiave). Se non si utilizza la variabile (ignored sopra) in nessun'altra parte del codice, non si fermerà l'oggetto dalla raccolta dei dati inutili.

+1

Grazie per la tua spiegazione! Molto apprezzato. –

+3

Ho visto questa domanda e immediatamente ho saputo che ci sarebbe stata una risposta da Jon Skeet ... ecco! – davnicwil

+0

@ Jon Skeet - Questo sarebbe il modo corretto di lanciarlo? IDictionary removefromColl = (IDictionary ) personColl; –

2

Dai un'occhiata all'articolo this.

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. 

Dal TryRemove rimuoverà l'oggetto da collezione, potrebbe essere necessario il valore della chiave.

È sicuro iterarlo con foreach. Non avrai un'eccezione.

+0

L'OP * ha * la chiave. Cosa ti fa pensare che non lo facciano? E ricorda che "sto solo usando questo codice per un esempio" - non c'è motivo di pensare che il codice reale non userà più thread. –

+0

Intendevo il valore di ciò a cui la chiave corrispondeva. Deve essere una cosa inglese americana. – DarthVader

+0

Ma il punto dell'OP è che * non * hanno bisogno di conoscere il valore corrispondente alla chiave ... quindi non erano sicuri di cosa fare con il parametro 'out'. Questo è il modo in cui ho risposto, comunque ... –