C# 线程安全的集合,无订单,无副本
我需要一个线程安全的集合来保存没有副本的项目C# 线程安全的集合,无订单,无副本,c#,.net,collections,concurrency,thread-safety,C#,.net,Collections,Concurrency,Thread Safety,我需要一个线程安全的集合来保存没有副本的项目ConcurrentBag允许非唯一项,并且HashSet不是线程安全的。在.NET Framework 4.5中是否有类似的集合?我建议您使用ConcurrentDictionary,并对每个条目使用一个伪值。就效率而言,这很烦人(有那么多虚拟值),但我怀疑在大多数应用程序中,这是无关紧要的 您可能希望将其封装在自己的ConcurrentSet实现中,这对于您的目的来说已经足够了,这样您就不需要看到大部分代码中的抽象漏洞了。以下是我刚刚编写的一些代码
ConcurrentBag
允许非唯一项,并且HashSet
不是线程安全的。在.NET Framework 4.5中是否有类似的集合?我建议您使用ConcurrentDictionary
,并对每个条目使用一个伪值。就效率而言,这很烦人(有那么多虚拟值),但我怀疑在大多数应用程序中,这是无关紧要的
您可能希望将其封装在自己的
ConcurrentSet
实现中,这对于您的目的来说已经足够了,这样您就不需要看到大部分代码中的抽象漏洞了。以下是我刚刚编写的一些代码,它实现了这个ConcurrentSet结构:
public class ConcurrentSet<T> : IEnumerable<T>, ISet<T>, ICollection<T>
{
private readonly ConcurrentDictionary<T, byte> _dictionary = new ConcurrentDictionary<T, byte>();
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<T> GetEnumerator()
{
return _dictionary.Keys.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(T item)
{
return TryRemove(item);
}
/// <summary>
/// Gets the number of elements in the set.
/// </summary>
public int Count
{
get { return _dictionary.Count; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
/// </returns>
public bool IsReadOnly { get { return false; } }
/// <summary>
/// Gets a value that indicates if the set is empty.
/// </summary>
public bool IsEmpty
{
get { return _dictionary.IsEmpty; }
}
public ICollection<T> Values
{
get { return _dictionary.Keys; }
}
/// <summary>
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
void ICollection<T>.Add(T item)
{
if(!Add(item))
throw new ArgumentException("Item already exists in set.");
}
/// <summary>
/// Modifies the current set so that it contains all elements that are present in both the current set and in the specified collection.
/// </summary>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public void UnionWith(IEnumerable<T> other)
{
foreach (var item in other)
TryAdd(item);
}
/// <summary>
/// Modifies the current set so that it contains only elements that are also in a specified collection.
/// </summary>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public void IntersectWith(IEnumerable<T> other)
{
var enumerable = other as IList<T> ?? other.ToArray();
foreach (var item in this)
{
if (!enumerable.Contains(item))
TryRemove(item);
}
}
/// <summary>
/// Removes all elements in the specified collection from the current set.
/// </summary>
/// <param name="other">The collection of items to remove from the set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public void ExceptWith(IEnumerable<T> other)
{
foreach (var item in other)
TryRemove(item);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public void SymmetricExceptWith(IEnumerable<T> other)
{
throw new NotImplementedException();
}
/// <summary>
/// Determines whether a set is a subset of a specified collection.
/// </summary>
/// <returns>
/// true if the current set is a subset of <paramref name="other"/>; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool IsSubsetOf(IEnumerable<T> other)
{
var enumerable = other as IList<T> ?? other.ToArray();
return this.AsParallel().All(enumerable.Contains);
}
/// <summary>
/// Determines whether the current set is a superset of a specified collection.
/// </summary>
/// <returns>
/// true if the current set is a superset of <paramref name="other"/>; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool IsSupersetOf(IEnumerable<T> other)
{
return other.AsParallel().All(Contains);
}
/// <summary>
/// Determines whether the current set is a correct superset of a specified collection.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Collections.Generic.ISet`1"/> object is a correct superset of <paramref name="other"/>; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set. </param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool IsProperSupersetOf(IEnumerable<T> other)
{
var enumerable = other as IList<T> ?? other.ToArray();
return this.Count != enumerable.Count && IsSupersetOf(enumerable);
}
/// <summary>
/// Determines whether the current set is a property (strict) subset of a specified collection.
/// </summary>
/// <returns>
/// true if the current set is a correct subset of <paramref name="other"/>; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool IsProperSubsetOf(IEnumerable<T> other)
{
var enumerable = other as IList<T> ?? other.ToArray();
return Count != enumerable.Count && IsSubsetOf(enumerable);
}
/// <summary>
/// Determines whether the current set overlaps with the specified collection.
/// </summary>
/// <returns>
/// true if the current set and <paramref name="other"/> share at least one common element; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool Overlaps(IEnumerable<T> other)
{
return other.AsParallel().Any(Contains);
}
/// <summary>
/// Determines whether the current set and the specified collection contain the same elements.
/// </summary>
/// <returns>
/// true if the current set is equal to <paramref name="other"/>; otherwise, false.
/// </returns>
/// <param name="other">The collection to compare to the current set.</param><exception cref="T:System.ArgumentNullException"><paramref name="other"/> is null.</exception>
public bool SetEquals(IEnumerable<T> other)
{
var enumerable = other as IList<T> ?? other.ToArray();
return Count == enumerable.Count && enumerable.AsParallel().All(Contains);
}
/// <summary>
/// Adds an element to the current set and returns a value to indicate if the element was successfully added.
/// </summary>
/// <returns>
/// true if the element is added to the set; false if the element is already in the set.
/// </returns>
/// <param name="item">The element to add to the set.</param>
public bool Add(T item)
{
return TryAdd(item);
}
public void Clear()
{
_dictionary.Clear();
}
public bool Contains(T item)
{
return _dictionary.ContainsKey(item);
}
/// <summary>
/// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type <paramref name="T"/> cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
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);
}
}
公共类ConcurrentSet:IEnumerable、ISet、ICollection
{
私有只读ConcurrentDictionary _dictionary=新ConcurrentDictionary();
///
///返回遍历集合的枚举数。
///
///
///可用于在集合中迭代的。
///
公共IEnumerator GetEnumerator()
{
返回_dictionary.Keys.GetEnumerator();
}
///
///返回遍历集合的枚举数。
///
///
///可用于在集合中迭代的对象。
///
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
///
///从中删除特定对象的第一个引用。
///
///
///如果已成功从中删除,则为true;否则为false。如果未在原始中找到,则此方法也返回false。
///
///要从中删除的对象。是只读的。
公共布尔删除(T项)
{
返回TryRemove(项目);
}
///
///获取集合中的元素数。
///
公共整数计数
{
获取{return\u dictionary.Count;}
}
///
///获取一个值,该值指示是否为只读。
///
///
///如果为只读,则为true;否则为false。
///
public bool IsReadOnly{get{return false;}}
///
///获取一个值,该值指示集合是否为空。
///
公共图书馆是空的
{
获取{return\u dictionary.IsEmpty;}
}
公共ICollection值
{
获取{return\u dictionary.Keys;}
}
///
///将项目添加到列表中。
///
///要添加到的对象。是只读的。
作废ICollection.Add(T项)
{
如果(!添加(项目))
抛出新ArgumentException(“集合中已存在项”);
}
///
///修改当前集合,使其包含当前集合和指定集合中存在的所有元素。
///
///要与当前集合进行比较的集合为空。
具有(IEnumerable other)的公共无效联合
{
foreach(其他中的var项目)
TryAdd(项目);
}
///
///修改当前集,使其仅包含也在指定集合中的元素。
///
///要与当前集合进行比较的集合为空。
与(IEnumerable other)相交的公共空间
{
var enumerable=other as IList??other.ToArray();
foreach(本文件中的var项目)
{
如果(!enumerable.Contains(项))
TryRemove(项目);
}
}
///
///从当前集合中删除指定集合中的所有元素。
///
///要从集合中删除的项集合。为空。
公共无效,例外情况(IEnumerable other)
{
foreach(其他中的var项目)
TryRemove(项目);
}
///
///修改当前集合,使其仅包含当前集合或指定集合中存在的元素,但不能同时包含这两个元素。
///
///要与当前集合进行比较的集合为空。
public void symmetricceExceptWith(IEnumerable其他)
{
抛出新的NotImplementedException();
}
///
///确定集合是否为指定集合的子集。
///
///
///如果当前集是的子集,则为true;否则为false。
///
///要与当前集合进行比较的集合为空。
公共资产发行量(IEnumerable other)
{
var enumerable=other as IList??other.ToArray();
返回此.AsParallel().All(enumerable.Contains);
}
///
///确定当前集合是否为指定集合的超集。
///
///
///如果当前集是的超集,则为true;否则为false。
///
///要与当前集合进行比较的集合为空。
公共布尔发布(IEnumerable other)
{
返回other.aspallel().All(Contains);
}
///
///确定当前集合是否是指定集合的正确超集。
///
///
///如果对象是的正确超集,则为true;否则为false。
///
///要与当前集合进行比较的集合为空。
公共布尔值ispropertsupersetof(IEnumerable其他)
{
var enumerable=other as IList??other.ToArray();
返回此.Count!=enumerable.Count&&IsSupersetOf(enumerable);
}
///
///确定当前集是否为指定集合的属性(严格)子集。
///
///
///如果当前集是的正确子集,则为true;否则为false。
///
///要与当前集合进行比较的集合为空。
公共布尔值为(IEnumerable other)
{
var enumerable=other as IList??other.ToArray();
返回计数!=enumerable.Count&&IsSubsetOf(enumerable);
}
///
///确定当前集合是否与指定集合重叠。
///
///
///如果当前设置并共享至少一个公共元素,则为true;ot