C# LRUCache类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class LRUCache<TKey, TValue> : where TValue : class
{
private Func<TValue, TKey> getKey;
private int maxCapacity;
private Dictionary<TKey, LinkedListNode<TValue>> buffer;
private LinkedList<TValue> list;
private ReaderWriterLockSlim locker;
public Func<TValue, TKey> GetKey
{
get { return getKey; }
}
public int Capacity
{
set { Interlocked.Exchange(ref maxCapacity, value); }
get { return maxCapacity; }
}
public int Count
{
get
{
locker.EnterReadLock();
try
{
return buffer.Count;
}
finally
{
locker.ExitReadLock();
}
}
}
public TValue LastItem
{
get
{
locker.EnterReadLock();
try
{
return list.Last.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
internal ReaderWriterLockSlim Locker
{
get { return locker; }
}
public TValue this[TKey key]
{
set
{
if (value == null)
{
locker.EnterUpgradeableReadLock();
try
{
LinkedListNode<TValue> node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.Remove(node);
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
else
{
AddFirst(key, value);
}
}
get
{
locker.EnterReadLock();
try
{
LinkedListNode<TValue> node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
list.Remove(node);
list.AddFirst(node);
}
finally
{
locker.ExitWriteLock();
}
}
return node.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
public LRUCache(Func<TValue, TKey> func)
: this(func, 500)
{
}
public LRUCache(Func<TValue, TKey> func, int capacity)
{
this.getKey = func;
this.maxCapacity = capacity * 10;
buffer = new Dictionary<TKey, LinkedListNode<TValue>>(capacity);
list = new LinkedList<TValue>();
locker = new ReaderWriterLockSlim();
}
public bool Contains(TKey key)
{
locker.EnterReadLock();
try
{
return buffer.ContainsKey(key);
}
finally
{
locker.ExitReadLock();
}
}
public void AddFirst(TKey key, TValue value)
{
AddFirst(key, value, Timeout.Infinite);
}
public void AddFirst(TKey key, TValue value, int timeout)
{
locker.EnterUpgradeableReadLock();
int count = buffer.Count;
if (count >= maxCapacity)
{
int needRemoveCount = count / 10;
locker.EnterWriteLock();
try
{
for (int i = 0; i < needRemoveCount; i++)
{
buffer.Remove(getKey(list.Last.Value));
list.RemoveLast();
}
}
finally
{
locker.ExitWriteLock();
}
}
try
{
LinkedListNode<TValue> node;
if (!buffer.TryGetValue(key, out node))
{
node = new LinkedListNode<TValue>(value);
if (locker.TryEnterWriteLock(timeout))
{
buffer.Add(key, node);
list.AddFirst(node);
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void RemoveLast()
{
locker.EnterUpgradeableReadLock();
try
{
if (list.Last != null)
{
TKey key = getKey(list.Last.Value);
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.RemoveLast();
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void Clear()
{
locker.EnterWriteLock();
try
{
buffer.Clear();
list.Clear();
}
finally
{
locker.ExitWriteLock();
}
}
}