线程安全集合,没有订单,也没有重复

我需要一个线程安全的集合来保存没有重复的项目。 ConcurrentBag允许HashSetHashSet不是线程安全的。 在.NET Framework 4.5中是否有这样的集合?

我建议你使用ConcurrentDictionary并为每个条目使用一个虚拟值。 它在效率方面很烦人(拥有所有那些虚拟值),但我怀疑在大多数应用程序中都是微不足道的。

您可能希望将它包装在您自己的ConcurrentSet实现中,这实现了您的目的,这样您就不需要在大部分代码中看到抽象泄漏。

这里是我刚刚编写的一些代码来实现这个ConcurrentSet构造:

 public class ConcurrentSet : IEnumerable, ISet, ICollection { private readonly ConcurrentDictionary _dictionary = new ConcurrentDictionary(); ///  /// Returns an enumerator that iterates through the collection. ///  ///  /// A  that can be used to iterate through the collection. ///  public IEnumerator GetEnumerator() { return _dictionary.Keys.GetEnumerator(); } ///  /// Returns an enumerator that iterates through a collection. ///  ///  /// An  object that can be used to iterate through the collection. ///  IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } ///  /// Removes the first occurrence of a specific object from the . ///  ///  /// true if  was successfully removed from the ; otherwise, false. This method also returns false if  is not found in the original . ///  /// The object to remove from the .The  is read-only. public bool Remove(T item) { return TryRemove(item); } ///  /// Gets the number of elements in the set. ///  public int Count { get { return _dictionary.Count; } } ///  /// Gets a value indicating whether the  is read-only. ///  ///  /// true if the  is read-only; otherwise, false. ///  public bool IsReadOnly { get { return false; } } ///  /// Gets a value that indicates if the set is empty. ///  public bool IsEmpty { get { return _dictionary.IsEmpty; } } public ICollection Values { get { return _dictionary.Keys; } } ///  /// Adds an item to the . ///  /// The object to add to the .The  is read-only. void ICollection.Add(T item) { if(!Add(item)) throw new ArgumentException("Item already exists in set."); } ///  /// Modifies the current set so that it contains all elements that are present in both the current set and in the specified collection. ///  /// The collection to compare to the current set. is null. public void UnionWith(IEnumerable other) { foreach (var item in other) TryAdd(item); } ///  /// Modifies the current set so that it contains only elements that are also in a specified collection. ///  /// The collection to compare to the current set. is null. public void IntersectWith(IEnumerable other) { var enumerable = other as IList ?? other.ToArray(); foreach (var item in this) { if (!enumerable.Contains(item)) TryRemove(item); } } ///  /// Removes all elements in the specified collection from the current set. ///  /// The collection of items to remove from the set. is null. public void ExceptWith(IEnumerable other) { foreach (var item in other) TryRemove(item); } ///  /// Modifies the current set so that it contains only elements that are present either in the current set or in the specified collection, but not both. ///  /// The collection to compare to the current set. is null. public void SymmetricExceptWith(IEnumerable other) { throw new NotImplementedException(); } ///  /// Determines whether a set is a subset of a specified collection. ///  ///  /// true if the current set is a subset of ; otherwise, false. ///  /// The collection to compare to the current set. is null. public bool IsSubsetOf(IEnumerable other) { var enumerable = other as IList ?? other.ToArray(); return this.AsParallel().All(enumerable.Contains); } ///  /// Determines whether the current set is a superset of a specified collection. ///  ///  /// true if the current set is a superset of ; otherwise, false. ///  /// The collection to compare to the current set. is null. public bool IsSupersetOf(IEnumerable other) { return other.AsParallel().All(Contains); } ///  /// Determines whether the current set is a correct superset of a specified collection. ///  ///  /// true if the  object is a correct superset of ; otherwise, false. ///  /// The collection to compare to the current set.  is null. public bool IsProperSupersetOf(IEnumerable other) { var enumerable = other as IList ?? other.ToArray(); return this.Count != enumerable.Count && IsSupersetOf(enumerable); } ///  /// Determines whether the current set is a property (strict) subset of a specified collection. ///  ///  /// true if the current set is a correct subset of ; otherwise, false. ///  /// The collection to compare to the current set. is null. public bool IsProperSubsetOf(IEnumerable other) { var enumerable = other as IList ?? other.ToArray(); return Count != enumerable.Count && IsSubsetOf(enumerable); } ///  /// Determines whether the current set overlaps with the specified collection. ///  ///  /// true if the current set and  share at least one common element; otherwise, false. ///  /// The collection to compare to the current set. is null. public bool Overlaps(IEnumerable other) { return other.AsParallel().Any(Contains); } ///  /// Determines whether the current set and the specified collection contain the same elements. ///  ///  /// true if the current set is equal to ; otherwise, false. ///  /// The collection to compare to the current set. is null. public bool SetEquals(IEnumerable other) { var enumerable = other as IList ?? other.ToArray(); return Count == enumerable.Count && enumerable.AsParallel().All(Contains); } ///  /// Adds an element to the current set and returns a value to indicate if the element was successfully added. ///  ///  /// true if the element is added to the set; false if the element is already in the set. ///  /// The element to add to the set. public bool Add(T item) { return TryAdd(item); } public void Clear() { _dictionary.Clear(); } public bool Contains(T item) { return _dictionary.ContainsKey(item); } ///  /// Copies the elements of the  to an , starting at a particular  index. ///  /// The one-dimensional  that is the destination of the elements copied from . The  must have zero-based indexing.The zero-based index in  at which copying begins. is null. is less than 0. is multidimensional.-or-The number of elements in the source  is greater than the available space from  to the end of the destination .-or-Type  cannot be cast automatically to the type of the destination . public void CopyTo(T[] array, int arrayIndex) { Values.CopyTo(array, arrayIndex); } public T[] ToArray() { return _dictionary.Keys.ToArray(); } public bool TryAdd(T item) { return _dictionary.TryAdd(item, default(byte)); } public bool TryRemove(T item) { byte donotcare; return _dictionary.TryRemove(item, out donotcare); } }