NullableKeyDictionary.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.Runtime.Collections
  5. {
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Runtime;
  11. class NullableKeyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
  12. {
  13. bool isNullKeyPresent;
  14. TValue nullKeyValue;
  15. IDictionary<TKey, TValue> innerDictionary;
  16. public NullableKeyDictionary()
  17. : base()
  18. {
  19. this.innerDictionary = new Dictionary<TKey, TValue>();
  20. }
  21. public int Count
  22. {
  23. get { return this.innerDictionary.Count + (this.isNullKeyPresent ? 1 : 0); }
  24. }
  25. public bool IsReadOnly
  26. {
  27. get { return false; }
  28. }
  29. public ICollection<TKey> Keys
  30. {
  31. get
  32. {
  33. return new NullKeyDictionaryKeyCollection<TKey, TValue>(this);
  34. }
  35. }
  36. public ICollection<TValue> Values
  37. {
  38. get { return new NullKeyDictionaryValueCollection<TKey, TValue>(this); }
  39. }
  40. public TValue this[TKey key]
  41. {
  42. get
  43. {
  44. if (key == null)
  45. {
  46. if (this.isNullKeyPresent)
  47. {
  48. return this.nullKeyValue;
  49. }
  50. else
  51. {
  52. throw Fx.Exception.AsError(new KeyNotFoundException());
  53. }
  54. }
  55. else
  56. {
  57. return this.innerDictionary[key];
  58. }
  59. }
  60. set
  61. {
  62. if (key == null)
  63. {
  64. this.isNullKeyPresent = true;
  65. this.nullKeyValue = value;
  66. }
  67. else
  68. {
  69. this.innerDictionary[key] = value;
  70. }
  71. }
  72. }
  73. public void Add(TKey key, TValue value)
  74. {
  75. if (key == null)
  76. {
  77. if (this.isNullKeyPresent)
  78. {
  79. throw Fx.Exception.Argument("key", InternalSR.NullKeyAlreadyPresent);
  80. }
  81. this.isNullKeyPresent = true;
  82. this.nullKeyValue = value;
  83. }
  84. else
  85. {
  86. this.innerDictionary.Add(key, value);
  87. }
  88. }
  89. public bool ContainsKey(TKey key)
  90. {
  91. return key == null ? this.isNullKeyPresent : this.innerDictionary.ContainsKey(key);
  92. }
  93. public bool Remove(TKey key)
  94. {
  95. if (key == null)
  96. {
  97. bool result = this.isNullKeyPresent;
  98. this.isNullKeyPresent = false;
  99. this.nullKeyValue = default(TValue);
  100. return result;
  101. }
  102. else
  103. {
  104. return this.innerDictionary.Remove(key);
  105. }
  106. }
  107. public bool TryGetValue(TKey key, out TValue value)
  108. {
  109. if (key == null)
  110. {
  111. if (this.isNullKeyPresent)
  112. {
  113. value = this.nullKeyValue;
  114. return true;
  115. }
  116. else
  117. {
  118. value = default(TValue);
  119. return false;
  120. }
  121. }
  122. else
  123. {
  124. return this.innerDictionary.TryGetValue(key, out value);
  125. }
  126. }
  127. public void Add(KeyValuePair<TKey, TValue> item)
  128. {
  129. Add(item.Key, item.Value);
  130. }
  131. public void Clear()
  132. {
  133. this.isNullKeyPresent = false;
  134. this.nullKeyValue = default(TValue);
  135. this.innerDictionary.Clear();
  136. }
  137. public bool Contains(KeyValuePair<TKey, TValue> item)
  138. {
  139. if (item.Key == null)
  140. {
  141. if (this.isNullKeyPresent)
  142. {
  143. return item.Value == null ? this.nullKeyValue == null : item.Value.Equals(this.nullKeyValue);
  144. }
  145. else
  146. {
  147. return false;
  148. }
  149. }
  150. else
  151. {
  152. return this.innerDictionary.Contains(item);
  153. }
  154. }
  155. public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
  156. {
  157. this.innerDictionary.CopyTo(array, arrayIndex);
  158. if (this.isNullKeyPresent)
  159. {
  160. array[arrayIndex + this.innerDictionary.Count] = new KeyValuePair<TKey, TValue>(default(TKey), this.nullKeyValue);
  161. }
  162. }
  163. public bool Remove(KeyValuePair<TKey, TValue> item)
  164. {
  165. if (item.Key == null)
  166. {
  167. if (this.Contains(item))
  168. {
  169. this.isNullKeyPresent = false;
  170. this.nullKeyValue = default(TValue);
  171. return true;
  172. }
  173. else
  174. {
  175. return false;
  176. }
  177. }
  178. else
  179. {
  180. return this.innerDictionary.Remove(item);
  181. }
  182. }
  183. public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  184. {
  185. IEnumerator<KeyValuePair<TKey, TValue>> innerEnumerator = this.innerDictionary.GetEnumerator() as IEnumerator<KeyValuePair<TKey, TValue>>;
  186. while (innerEnumerator.MoveNext())
  187. {
  188. yield return innerEnumerator.Current;
  189. }
  190. if (this.isNullKeyPresent)
  191. {
  192. yield return new KeyValuePair<TKey, TValue>(default(TKey), this.nullKeyValue);
  193. }
  194. }
  195. IEnumerator IEnumerable.GetEnumerator()
  196. {
  197. return ((IEnumerable<KeyValuePair<TKey, TValue>>)this).GetEnumerator();
  198. }
  199. class NullKeyDictionaryKeyCollection<TypeKey, TypeValue> : ICollection<TypeKey>
  200. {
  201. NullableKeyDictionary<TypeKey, TypeValue> nullKeyDictionary;
  202. public NullKeyDictionaryKeyCollection(NullableKeyDictionary<TypeKey, TypeValue> nullKeyDictionary)
  203. {
  204. this.nullKeyDictionary = nullKeyDictionary;
  205. }
  206. public int Count
  207. {
  208. get
  209. {
  210. int count = this.nullKeyDictionary.innerDictionary.Keys.Count;
  211. if (this.nullKeyDictionary.isNullKeyPresent)
  212. {
  213. count++;
  214. }
  215. return count;
  216. }
  217. }
  218. public bool IsReadOnly
  219. {
  220. get { return true; }
  221. }
  222. public void Add(TypeKey item)
  223. {
  224. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.KeyCollectionUpdatesNotAllowed));
  225. }
  226. public void Clear()
  227. {
  228. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.KeyCollectionUpdatesNotAllowed));
  229. }
  230. public bool Contains(TypeKey item)
  231. {
  232. return item == null ? this.nullKeyDictionary.isNullKeyPresent : this.nullKeyDictionary.innerDictionary.Keys.Contains(item);
  233. }
  234. public void CopyTo(TypeKey[] array, int arrayIndex)
  235. {
  236. this.nullKeyDictionary.innerDictionary.Keys.CopyTo(array, arrayIndex);
  237. if (this.nullKeyDictionary.isNullKeyPresent)
  238. {
  239. array[arrayIndex + this.nullKeyDictionary.innerDictionary.Keys.Count] = default(TypeKey);
  240. }
  241. }
  242. public bool Remove(TypeKey item)
  243. {
  244. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.KeyCollectionUpdatesNotAllowed));
  245. }
  246. public IEnumerator<TypeKey> GetEnumerator()
  247. {
  248. foreach (TypeKey item in this.nullKeyDictionary.innerDictionary.Keys)
  249. {
  250. yield return item;
  251. }
  252. if (this.nullKeyDictionary.isNullKeyPresent)
  253. {
  254. yield return default(TypeKey);
  255. }
  256. }
  257. IEnumerator IEnumerable.GetEnumerator()
  258. {
  259. return ((IEnumerable<TypeKey>)this).GetEnumerator();
  260. }
  261. }
  262. class NullKeyDictionaryValueCollection<TypeKey, TypeValue> : ICollection<TypeValue>
  263. {
  264. NullableKeyDictionary<TypeKey, TypeValue> nullKeyDictionary;
  265. public NullKeyDictionaryValueCollection(NullableKeyDictionary<TypeKey, TypeValue> nullKeyDictionary)
  266. {
  267. this.nullKeyDictionary = nullKeyDictionary;
  268. }
  269. public int Count
  270. {
  271. get
  272. {
  273. int count = this.nullKeyDictionary.innerDictionary.Values.Count;
  274. if (this.nullKeyDictionary.isNullKeyPresent)
  275. {
  276. count++;
  277. }
  278. return count;
  279. }
  280. }
  281. public bool IsReadOnly
  282. {
  283. get { return true; }
  284. }
  285. public void Add(TypeValue item)
  286. {
  287. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.ValueCollectionUpdatesNotAllowed));
  288. }
  289. public void Clear()
  290. {
  291. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.ValueCollectionUpdatesNotAllowed));
  292. }
  293. public bool Contains(TypeValue item)
  294. {
  295. return this.nullKeyDictionary.innerDictionary.Values.Contains(item) ||
  296. (this.nullKeyDictionary.isNullKeyPresent && this.nullKeyDictionary.nullKeyValue.Equals(item));
  297. }
  298. public void CopyTo(TypeValue[] array, int arrayIndex)
  299. {
  300. this.nullKeyDictionary.innerDictionary.Values.CopyTo(array, arrayIndex);
  301. if (this.nullKeyDictionary.isNullKeyPresent)
  302. {
  303. array[arrayIndex + this.nullKeyDictionary.innerDictionary.Values.Count] = this.nullKeyDictionary.nullKeyValue;
  304. }
  305. }
  306. public bool Remove(TypeValue item)
  307. {
  308. throw Fx.Exception.AsError(new NotSupportedException(InternalSR.ValueCollectionUpdatesNotAllowed));
  309. }
  310. public IEnumerator<TypeValue> GetEnumerator()
  311. {
  312. foreach (TypeValue item in this.nullKeyDictionary.innerDictionary.Values)
  313. {
  314. yield return item;
  315. }
  316. if (this.nullKeyDictionary.isNullKeyPresent)
  317. {
  318. yield return this.nullKeyDictionary.nullKeyValue;
  319. }
  320. }
  321. IEnumerator IEnumerable.GetEnumerator()
  322. {
  323. return ((IEnumerable<TypeValue>)this).GetEnumerator();
  324. }
  325. }
  326. }
  327. }