1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections.Generic;
19 using System.Diagnostics;
21 namespace Microsoft.Scripting.Utils {
23 /// A hybrid dictionary which compares based upon object identity.
25 class HybridReferenceDictionary<TKey, TValue> where TKey : class {
26 private KeyValuePair<TKey, TValue>[] _keysAndValues;
27 private Dictionary<TKey, TValue> _dict;
29 private const int _arraySize = 10;
31 public HybridReferenceDictionary() {
34 public HybridReferenceDictionary(int initialCapicity) {
35 if (initialCapicity > _arraySize) {
36 _dict = new Dictionary<TKey, TValue>(initialCapicity);
38 _keysAndValues = new KeyValuePair<TKey, TValue>[initialCapicity];
42 public bool TryGetValue(TKey key, out TValue value) {
43 Debug.Assert(key != null);
46 return _dict.TryGetValue(key, out value);
47 } else if (_keysAndValues != null) {
48 for (int i = 0; i < _keysAndValues.Length; i++) {
49 if (_keysAndValues[i].Key == key) {
50 value = _keysAndValues[i].Value;
55 value = default(TValue);
59 public bool Remove(TKey key) {
60 Debug.Assert(key != null);
63 return _dict.Remove(key);
64 } else if (_keysAndValues != null) {
65 for (int i = 0; i < _keysAndValues.Length; i++) {
66 if (_keysAndValues[i].Key == key) {
67 _keysAndValues[i] = new KeyValuePair<TKey, TValue>();
77 public bool ContainsKey(TKey key) {
78 Debug.Assert(key != null);
81 return _dict.ContainsKey(key);
82 } else if (_keysAndValues != null) {
83 for (int i = 0; i < _keysAndValues.Length; i++) {
84 if (_keysAndValues[i].Key == key) {
103 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
105 return _dict.GetEnumerator();
108 return GetEnumeratorWorker();
111 private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorWorker() {
112 if (_keysAndValues != null) {
113 for (int i = 0; i < _keysAndValues.Length; i++) {
114 if (_keysAndValues[i].Key != null) {
115 yield return _keysAndValues[i];
121 public TValue this[TKey key] {
123 Debug.Assert(key != null);
126 if (TryGetValue(key, out res)) {
130 throw new KeyNotFoundException();
133 Debug.Assert(key != null);
139 if (_keysAndValues != null) {
141 for (int i = 0; i < _keysAndValues.Length; i++) {
142 if (_keysAndValues[i].Key == key) {
143 _keysAndValues[i] = new KeyValuePair<TKey, TValue>(key, value);
145 } else if (_keysAndValues[i].Key == null) {
150 _keysAndValues = new KeyValuePair<TKey, TValue>[_arraySize];
156 _keysAndValues[index] = new KeyValuePair<TKey, TValue>(key, value);
158 _dict = new Dictionary<TKey, TValue>();
159 for (int i = 0; i < _keysAndValues.Length; i++) {
160 _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value;
162 _keysAndValues = null;