例としてこのコードを使用しています。次の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);
}
}
これは、並行辞書を反復処理する安全な方法ですか?そうでない場合、それを行うための安全な方法は何ですか?
辞書からPersonオブジェクトを削除したいとしましょう。 tryRemoveメソッドを使用しますが、outPersonオブジェクトをどうすればよいですか?辞書から削除されたPersonはそこに保存されます。 outPersonオブジェクトを完全に消去するにはどうすればよいですか?
これは、並行辞書を反復処理する安全な方法ですか?そうでない場合、それを行うための安全な方法は何ですか?
はい、例外をスローしないという点で安全です。反復の開始後に要素が追加または削除された場合、それらの要素は反復に含まれる場合と含まれない場合があります。 GetEnumerator
ドキュメントから:
ディクショナリから返される列挙子は、ディクショナリの読み取りおよび書き込みと同時に使用しても安全ですが、ディクショナリの瞬間的なスナップショットを表すものではありません。列挙子を介して公開されるコンテンツには、GetEnumeratorが呼び出された後に辞書に加えられた変更が含まれる場合があります。
次:
TryRemoveメソッドを使用しますが、outPersonオブジェクトをどうすればよいですか?
何も含めて、何でも必要です。辞書をIDictionary<TKey, TValue>
にキャストしてRemove
を呼び出すか、単にTryRemove
を使用して変数を無視できます。
Person ignored;
dictionary.TryRemove(key, out ignored);
「[オブジェクト]を完全にクリアする」という概念はありません。参照がなければ、ガベージコレクションされます。しかし、どちらにしても、少なくとも辞書にはありません(少なくともそのキーを介して)。コードの他の場所で変数(上記のignored
)を使用しない場合、オブジェクトのガベージコレクションが停止することはありません。
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.
TryRemoveはアイテムをコレクションから削除するため、キーの値が必要になる場合があります。
Foreachで繰り返し処理するのは安全です。あなたは例外を取得しません。