using System.Collections.Generic;
using System.Diagnostics;
public static void Main()
Debug.Listeners.Add(new TextWriterTraceListener(System.Console.Out));
Debug.WriteLine("Testing...");
var memCache = new Cache<string,string>();
Debug.WriteLine("Cache class testing...");
memCache.create(2,new EvictMock1<string>());
Debug.WriteLine(memCache != null);
Debug.WriteLine(memCache.get("any-item") == null);
Debug.WriteLine(memCache.exists("any-item") == false);
memCache.add("key1","value1");
Debug.WriteLine(memCache.get("key1") == "value1");
memCache.add("key2","value2");
Debug.WriteLine(memCache.exists("key2") == true);
memCache.add("key3", "value2");
Debug.WriteLine(memCache.exists("key3") == false);
Debug.WriteLine("FIFO testing...");
IEvictionStrategy<string> fifo = new EvictFIFO<string>();
var keyToRemove = fifo.OnAdd("key1");
Debug.WriteLine(keyToRemove == null);
keyToRemove = fifo.OnAdd("key2");
Debug.WriteLine(keyToRemove == null);
keyToRemove = fifo.OnAdd("key3");
Debug.WriteLine(keyToRemove == "key1");
Debug.WriteLine("LRU testing...");
IEvictionStrategy<string> lru = new EvictLRU<string>();
keyToRemove = lru.OnAdd("key1");
Debug.WriteLine(keyToRemove == null);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.5));
keyToRemove = lru.OnAdd("key2");
Debug.WriteLine(keyToRemove == null);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.5));
keyToRemove = lru.OnAdd("key3");
Debug.WriteLine(keyToRemove == "key1");
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.5));
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.5));
keyToRemove = lru.OnAdd("key4");
Debug.WriteLine(keyToRemove == "key3");
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.5));
keyToRemove = lru.OnAdd("key5");
Debug.WriteLine(keyToRemove == "key2");
Debug.WriteLine("Random strategy testing...");
IEvictionStrategy<string> random = new EvictRandom<string>();
memCache = new Cache<string,string>();
memCache.create(5,random);
memCache.add("key1","value1");
memCache.add("key2","value2");
memCache.add("key3","value3");
memCache.add("key4","value4");
memCache.add("key5","value5");
Debug.WriteLine((new string[]{"key1","key2","key3","key4","key5"}).Count(o=> memCache.exists(o)) == 5);
memCache.add("key6","value6");
Debug.WriteLine(memCache.exists("key6"));
Debug.WriteLine((new string[]{"key1","key2","key3","key4","key5"}).Count(o=>!memCache.exists(o)) == 1);
public class Cache<T1, T2>
private IDictionary<T1, T2> _inMemoryCache;
private IEvictionStrategy<T1> _evictionStrategy;
public void create(int size, IEvictionStrategy<T1> evictionStrategy)
if (_inMemoryCache == null)
_inMemoryCache = new Dictionary<T1, T2>(size);
_evictionStrategy = evictionStrategy;
_evictionStrategy.SetSize(size);
public void add(T1 key, T2 keyValue)
Debug.Assert(_inMemoryCache != null);
Debug.Assert(_evictionStrategy != null);
if (_inMemoryCache.ContainsKey(key))
_inMemoryCache[key] = keyValue;
_inMemoryCache.Add(key, keyValue);
T1 keyToRemove = _evictionStrategy.OnAdd(key);
_inMemoryCache.Remove(keyToRemove);
Debug.Assert(_inMemoryCache.Count <= _size);
if (_inMemoryCache == null || !_inMemoryCache.ContainsKey(key))
Debug.Assert(_evictionStrategy != null);
_evictionStrategy.OnGet(key);
return _inMemoryCache[key];
public bool exists(T1 key)
if (_inMemoryCache == null || !_inMemoryCache.ContainsKey(key))
public interface IEvictionStrategy<T1>
public class EvictMock1<T1> : IEvictionStrategy<T1>
if(_list.Count == _list.Capacity)
public void OnGet(T1 key)
Debug.WriteLine("OnGet Called " + key.ToString());
public void SetSize(int size)
_list = new List<T1>(size);
public class EvictLRU<T1> : IEvictionStrategy<T1>
private Dictionary<T1, long> _list;
T1 keyToRemove = default(T1);
if(!_list.ContainsKey(key)){
var enumerator = _list.GetEnumerator();
long oldest = long.MaxValue;
while(enumerator.MoveNext())
if(oldest > enumerator.Current.Value){
keyToRemove = enumerator.Current.Key;
oldest = enumerator.Current.Value;
_list.Remove(keyToRemove);
_list.Add(key,DateTime.UtcNow.Ticks);
_list[key] = DateTime.UtcNow.Ticks;
public void OnGet(T1 key)
_list[key] = DateTime.UtcNow.Ticks;
public void SetSize(int size)
_list = new Dictionary<T1, long>(size);
public class EvictFIFO<T1> : IEvictionStrategy<T1>
T1 keyToRemove = default(T1);
Debug.Assert(_list != null, "Call SetSize method before calling this method");
if(!_list.Contains(key) && _list.Count >= _size){
T1[] keyArray = _list.ToArray();
keyToRemove = keyArray[0];
var newList = new List<T1>(_size);
var enumerator = _list.GetEnumerator();
while(enumerator.MoveNext() && !enumerator.Current.Equals(key))
newList.Add(enumerator.Current);
_list = new Queue<T1>(newList);
public void OnGet(T1 key)
public void SetSize(int size)
_list = new Queue<T1>(size);
public class EvictRandom<T1> : IEvictionStrategy<T1>
T1 keyToRemove = default(T1);
if(_list.Count >= _size && !_list.Contains(key)){
int indexToRemove = new Random().Next(_size);
keyToRemove = _list[indexToRemove];
_list.RemoveAt(indexToRemove);
else if (!_list.Contains(key)){
public void OnGet(T1 key)
public void SetSize(int size)
_list = new List<T1>(size);