diff --git a/ExtraCollectionSharp/ExtraCollectionSharp.csproj b/ExtraCollectionSharp/ExtraCollectionSharp.csproj
new file mode 100644
index 0000000..f208d30
--- /dev/null
+++ b/ExtraCollectionSharp/ExtraCollectionSharp.csproj
@@ -0,0 +1,7 @@
+
+
+
+ net5.0
+
+
+
diff --git a/ExtraCollectionSharp/LRUCache.cs b/ExtraCollectionSharp/LRUCache.cs
new file mode 100644
index 0000000..e9bab3c
--- /dev/null
+++ b/ExtraCollectionSharp/LRUCache.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ExtraCollectionSharp
+{
+public class LRUCache : IEnumerable
+ {
+ private class Node
+ {
+ public K key;
+ public V value;
+ public Node front;
+ public Node back;
+ }
+
+ public int Size {get { return size; } }
+ public int Count {get { return valueDictionary.Count; } }
+ private readonly int size;
+ private Node top;
+ private Node bottom;
+ private Dictionary valueDictionary;
+ private Action cleanupAction;
+
+ public LRUCache(int size = 100, Action cleanup = null)
+ {
+ this.size = size;
+ valueDictionary = new Dictionary(size);
+ this.cleanupAction = cleanup;
+ }
+
+ private void MoveToTop(K key) {
+ Node node = valueDictionary[key];
+ if (node != null && top != node) {
+ node.front.back = node.back;
+ node.back = top;
+ node.front = null;
+ top = node;
+ }
+ }
+
+ private Node AddToTop(K key, V value) {
+ Node node = new Node();
+ node.front = null;
+ node.back = top;
+ node.value = value;
+ node.key = key;
+ top = node;
+ if (bottom == null) {
+ bottom = node;
+ } else if (valueDictionary.Count == Size) {
+ valueDictionary.Remove(bottom.key);
+ cleanupAction?.Invoke(bottom.value);
+ bottom = bottom.front;
+ }
+ valueDictionary[key] = node;
+ return node;
+ }
+
+ public V Use(K key, Func generate) {
+ if (generate == null) throw new ArgumentNullException("generate");
+ Node value = null;
+ if (valueDictionary.ContainsKey(key)) {
+ value = valueDictionary[key];
+ MoveToTop(key);
+ } else {
+ value = AddToTop(key, generate());
+ }
+ return value.value;
+ }
+
+ public bool IsCached(K key) {
+ return valueDictionary.ContainsKey(key);
+ }
+
+ public void Clear() {
+ top = null;
+ bottom = null;
+ valueDictionary.Clear();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach (Node node in valueDictionary.Values)
+ {
+ yield return node.value;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}