.NET(3.5まで)のコレクションは、スレッドセーフまたは非ブロッキング(並列実行)ではありません。IListから派生して実装し、すべてのアクションを実行するためにReaderWriterLockSlimを使用する必要があります。たとえば、Addメソッドは次のようになります。
public void Add(T item)
{
_readerWriterLockSlim.EnterWriteLock();
try { _actualList.Add(item); }
finally { _readerWriterLockSlim.ExitWriteLock(); }
}
ここでは、いくつかの並行性のトリックに注意する必要があります。たとえば、新しいインスタンスをIListとして返すGetEnumeratorが必要です。実際のリストではありません。そうしないと、問題が発生します。これは次のようになります。
public IEnumerator<T> GetEnumerator()
{
List<T> localList;
_lock.EnterReadLock();
try { localList= new List<T>(_actualList); }
finally { _lock.ExitReadLock(); }
foreach (T item in localList) yield return item;
}
と:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
注:スレッドセーフまたは並列コレクション(および実際には他のすべてのクラス)を実装する場合は、クラスから派生しないでください。ただし、インターフェースを使用してください。そのクラスの内部構造や仮想ではないいくつかのメソッドに関連する問題が常にあり、それらを非表示にする必要があるためなどです。これを行う必要がある場合は、慎重に行ってください。