I am trying to implement a ConcurrentHashSet in the spirit of ConcurrentDictionary, approach taken is to use a internal backing ConcurrentDictionary and write small delegating methods, this is how far i got, but well the set theoretic methods are I am stuck on, esp. I am not sure if I can use a foreach and still not violate concurrency
public class ConcurrentHashSet<TElement> : ISet<TElement>
{
private readonly ConcurrentDictionary<TElement, object> _internal;
public ConcurrentHashSet(IEnumerable<TElement> elements = null)
{
_internal = new ConcurrentDictionary<TElement, object>();
if (elements != null)
UnionWith(elements);
}
public void UnionWith(IEnumerable<TElement> other)
{
if (other == null) throw new ArgumentNullException("other");
foreach (var otherElement in other)
Add(otherElement);
}
public void IntersectWith(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public void ExceptWith(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public void SymmetricExceptWith(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public bool IsSubsetOf(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public bool IsSupersetOf(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public bool IsProperSupersetOf(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public bool IsProperSubsetOf(IEnumerable<TElement> other)
{
throw new NotImplementedException();
}
public bool Overlaps(IEnumerable<TElement> other)
{
return other.Any(otherElement => _internal.ContainsKey(otherElement));
}
public bool SetEquals(IEnumerable<TElement> other)
{
int otherCount = 0;
int thisCount = Count;
foreach (var otherElement in other)
{
otherCount++;
if (!_internal.ContainsKey(otherElement))
return false;
}
return otherCount == thisCount;
}
public bool Add(TElement item)
{
return _internal.TryAdd(item, null);
}
public void Clear()
{
_internal.Clear();
}
// I am not sure here if that fullfills contract correctly
void ICollection<TElement>.Add(TElement item)
{
Add(item);
}
public bool Contains(TElement item)
{
return _internal.ContainsKey(item);
}
public void CopyTo(TElement[] array, int arrayIndex)
{
_internal.Keys.CopyTo(array, arrayIndex);
}
public bool Remove(TElement item)
{
object ignore;
return _internal.TryRemove(item, out ignore);
}
public int Count
{
get { return _internal.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public IEnumerator<TElement> GetEnumerator()
{
return _internal.Keys.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I just ran into a similar scenario ("I am interested in a fast Add and Contains and Remove") and implemented this sucker:
using System.Collections.Generic;
using System.Threading;
namespace BlahBlah.Utilities
{
public class ConcurrentHashSet<T> : IDisposable
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private readonly HashSet<T> _hashSet = new HashSet<T>();
#region Implementation of ICollection<T> ...ish
public bool Add(T item)
{
try
{
_lock.EnterWriteLock();
return _hashSet.Add(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public void Clear()
{
try
{
_lock.EnterWriteLock();
_hashSet.Clear();
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public bool Contains(T item)
{
try
{
_lock.EnterReadLock();
return _hashSet.Contains(item);
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
public bool Remove(T item)
{
try
{
_lock.EnterWriteLock();
return _hashSet.Remove(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public int Count
{
get
{
try
{
_lock.EnterReadLock();
return _hashSet.Count;
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
}
#endregion
#region Dispose
public void Dispose()
{
if (_lock != null) _lock.Dispose();
}
#endregion
}
}
Haven't really tested it (performance- or reliability-wise). YMMV.