1 #if DEBUG && MODBREAKER
4 using System.Collections;
5 using System.Collections.Generic;
17 public class CursedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue> where TKey: notnull
19 private ICollection<TKey> keys;
20 private ICollection<TValue> values;
21 private readonly List<KeyValuePair<TKey, TValue>> keyValuePairs =
new List<KeyValuePair<TKey, TValue>>();
22 private readonly Dictionary<TKey, int> keyToKvpIndex =
new Dictionary<TKey, int>();
23 private readonly
object mutex =
new object();
25 private readonly
Random rng;
27 public CursedDictionary()
29 rng =
new Random((
int)(DateTime.Now.ToBinary() %
int.MaxValue));
30 keys = Array.Empty<TKey>();
31 values = Array.Empty<TValue>();
34 private void Refresh()
36 keys = keyValuePairs.Select(kvp => kvp.Key).ToArray();
37 values = keyValuePairs.Select(kvp => kvp.Value).ToArray();
38 keyToKvpIndex.Clear();
39 for (
int i=0; i<keyValuePairs.Count; i++)
41 keyToKvpIndex[keyValuePairs[i].Key] = i;
45 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
47 KeyValuePair<TKey, TValue>[] clone;
50 keyValuePairs.Shuffle(rng);
52 clone = keyValuePairs.ToArray();
55 foreach (var kvp
in clone)
61 IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
63 public void Add(KeyValuePair<TKey, TValue> item)
67 if (keyToKvpIndex.ContainsKey(item.Key))
69 throw new InvalidOperationException($
"Duplicate key: {item.Key}");
72 keyValuePairs.Add(item);
73 keyValuePairs.Shuffle(rng);
82 keyValuePairs.Clear();
87 public bool Contains(KeyValuePair<TKey, TValue> item)
91 return keyValuePairs.Contains(item);
95 public void CopyTo(KeyValuePair<TKey, TValue>[] array,
int arrayIndex)
99 keyValuePairs.Shuffle(rng);
100 keyValuePairs.CopyTo(array, arrayIndex);
105 public bool Remove(KeyValuePair<TKey, TValue> item)
109 bool success = keyValuePairs.Remove(item);
110 keyValuePairs.Shuffle(rng);
122 return keyValuePairs.Count;
127 public bool IsReadOnly =>
false;
129 public void Add(TKey key, TValue value) => Add(
new KeyValuePair<TKey, TValue>(key, value));
131 public bool ContainsKey(TKey key)
135 return keyToKvpIndex.ContainsKey(key);
139 public bool TryGetValue(TKey key, out TValue value)
144 bool success = keyToKvpIndex.TryGetValue(key, out
int index);
147 value = keyValuePairs[index].Value;
150 keyValuePairs.Shuffle(rng);
156 public bool Remove(TKey key) => TryRemove(key, out _);
158 public bool TryRemove(TKey key, out TValue value)
163 bool success =
false;
164 if (keyToKvpIndex.TryGetValue(key, out
int index))
166 value = keyValuePairs[index].Value;
167 keyValuePairs.RemoveAt(index);
171 keyValuePairs.Shuffle(rng);
177 public TValue
this[TKey key]
183 return keyValuePairs[keyToKvpIndex[key]].Value;
190 if (!keyToKvpIndex.ContainsKey(key))
196 keyValuePairs[keyToKvpIndex[key]] =
new KeyValuePair<TKey, TValue>(key, value);
199 keyValuePairs.Shuffle(rng);
206 public ICollection<TKey> Keys
212 return keys.ToArray();
216 public ICollection<TValue> Values
222 return values.ToArray();
227 IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
228 IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;