/// <summary> /// Removes the mapping for this key from this map if present. /// </summary> /// <remarks> /// Expensive: updates both the underlying cache and the local cache. /// </remarks> /// <param name="key"> /// The key of the element to remove. /// </param> /// <returns> /// Previous value associated with specified key, or <c>null</c> if /// there was no mapping for key. A <c>null</c> return can also /// indicate that the dictionary previously associated <c>null</c> /// with the specified key, if the implementation supports /// <c>null</c> values. /// </returns> public virtual object RemoveEx(object key) { switch (m_implType) { case LiteDictionaryType.Empty: return(null); case LiteDictionaryType.Single: DictionaryEntry entry = (DictionaryEntry)m_contents; object keyEntry = entry.Key; object prev = null; if (Equals(key, keyEntry)) { prev = entry.Value; m_implType = LiteDictionaryType.Empty; m_contents = null; } return(prev); case LiteDictionaryType.Array1: case LiteDictionaryType.Array2: case LiteDictionaryType.Array3: case LiteDictionaryType.Array4: case LiteDictionaryType.Array5: case LiteDictionaryType.Array6: case LiteDictionaryType.Array7: case LiteDictionaryType.Array8: LiteDictionaryType impl = m_implType; DictionaryEntry[] entries = (DictionaryEntry[])m_contents; int c = impl - LiteDictionaryType.Array1 + 1; int i = IndexOf(entries, c, key); if (i < 0) { return(null); } object prevValue = entries[i].Value; if (c == 1) { m_implType = LiteDictionaryType.Empty; m_contents = null; } else { Array.Copy(entries, i + 1, entries, i, c - i - 1); // cannot set entries[c - 1] to null as in Java code // initialize to empty DictionaryEntry instead entries[c - 1] = new DictionaryEntry(); m_implType = --impl; } return(prevValue); case LiteDictionaryType.Other: IDictionary map = (IDictionary)m_contents; object prevVal = map[key]; map.Remove(key); CheckShrinkFromOther(); return(prevVal); default: throw new InvalidOperationException(); } }
/// <summary> /// Adds an element with the provided key and value to the /// <b>IDictionary</b> object. /// </summary> /// <param name="value"> /// The object to use as the value of the element to add. /// </param> /// <param name="key"> /// The object to use as the key of the element to add. /// </param> public virtual void Add(object key, object value) { switch (m_implType) { case LiteDictionaryType.Empty: m_implType = LiteDictionaryType.Single; m_contents = InstantiateEntry(key, value); break; case LiteDictionaryType.Single: DictionaryEntry entry = (DictionaryEntry)m_contents; object keyEntry = entry.Key; if (Equals(key, keyEntry)) { entry.Value = value; m_contents = entry; } else { // grow to array implementation DictionaryEntry[] entries = new DictionaryEntry[THRESHOLD]; entries[0] = entry; entries[1] = InstantiateEntry(key, value); m_implType = LiteDictionaryType.Array2; m_contents = entries; } break; case LiteDictionaryType.Array1: case LiteDictionaryType.Array2: case LiteDictionaryType.Array3: case LiteDictionaryType.Array4: case LiteDictionaryType.Array5: case LiteDictionaryType.Array6: case LiteDictionaryType.Array7: case LiteDictionaryType.Array8: LiteDictionaryType impl = m_implType; DictionaryEntry[] entriesArray = (DictionaryEntry[])m_contents; int c = impl - LiteDictionaryType.Array1 + 1; int i = IndexOf(entriesArray, c, key); if (i >= 0) { entriesArray[i].Value = value; } else { // check if adding the object exceeds the "lite" threshold if (c >= THRESHOLD) { // time to switch to a different map implementation IDictionary map = InstantiateDictionary(); for (i = 0; i < c; ++i) { DictionaryEntry entr = entriesArray[i]; map.Add(entr.Key, entr.Value); } map.Add(key, value); m_implType = LiteDictionaryType.Other; m_contents = map; } else { // use the next available element in the array entriesArray[c] = InstantiateEntry(key, value); m_implType = impl + 1; m_contents = entriesArray; } } break; case LiteDictionaryType.Other: ((IDictionary)m_contents)[key] = value; break; default: throw new InvalidOperationException(); } }