[英]Using LINQ methods on a custom ConcurrentHashSet class?
最近,我從HashSet切換到其他人發布的集合,名為“ ConcurrentHashSet”,我決定不鎖定自己的HashSet,因為我經常使用它,並且似乎更安全的選擇是使用預制的線程安全類,但我遇到了一個問題。
當我使用HashSet(默認的HashSet類)時,我正在使用First
和FirstOrDefault
方法獲取HashSet值,問題是我無法再使用這些方法,而且我不確定為什么或如何重新實現它們,是FirstOrDefault
甚至可能嗎? 我不確定這可能真的很簡單。
我希望有人會知道並且可以指出正確的方向。 這是我從另一個堆棧溢出答案中獲得的類,盡管我不確定這是否是原始的。
public class ConcurrentHashSet<T> : IDisposable
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private readonly HashSet<T> _hashSet = new HashSet<T>();
public bool TryAdd(T item)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Add(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public void Clear()
{
_lock.EnterWriteLock();
try
{
_hashSet.Clear();
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public bool Contains(T item)
{
_lock.EnterReadLock();
try
{
return _hashSet.Contains(item);
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
public bool TryRemove(T item)
{
_lock.EnterWriteLock();
try
{
return _hashSet.Remove(item);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public int Count
{
get
{
_lock.EnterReadLock();
try
{
return _hashSet.Count;
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_lock?.Dispose();
}
}
~ConcurrentHashSet()
{
Dispose(false);
}
}
在內部發布的自定義類使用HashSet<T>
來存儲數據。 因此,您仍然可以使用提到的方法First
和FirstOrDefault
, 只要您以線程安全的方式進行操作即可 。 例如, FirstOrDefault
的實現應該是這樣的:
public T TryGetFirstOrDefault()
{
_lock.EnterReadLock();
try
{
return _hashSet.FirstOrDefault();
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
更新
您可以通過傳遞謂詞來概括以上內容:
public T TryGetFirstOrDefault(Func<T, bool> predicate)
{
_lock.EnterReadLock();
try
{
return _hashSet.FirstOrDefault(x=>predicate(x));
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
因此,如果您有ConcurrentHashSet<Player>
,則可以將其用作例如:
var player = concurrentHashSetOfPlayers.TryGetFirstOrDefault(x=>x.Id == playerId);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.