I suggest you ...

Add TryRemove(TKey key, out TValue value) to Dictionary<TKey, TValue>

Currently, to "pull" an item out of a Dictionary it is a two step process:

SomeClass value = null;
if (dictionary.TryGetValue(theKey, out value))
{
dictionary.Remove(theKey);
// do something with the item...
}

This requires the hash code to be generated twice, which can be costly in high performance scenarios (which is why TryGetValue exists in the first place).

It would be optimal to be able to do:

SomeClass value = null;
if (dictionary.TryRemove(theKey, out value))
{
// do something with the item...
}

Implementation would be trivial and provide significant benefit.

391 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Ryan Rastedt shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    12 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      Signed in as (Sign out)
      Submitting...
      • h82258652 commented  ·   ·  Flag as inappropriate

        this is a no bad idea.
        you can use extension method to do this.
        but I still hope add this method in the next .net version.

      • Branko Dimitrijevic commented  ·   ·  Flag as inappropriate

        Maybe we could generalize it like this:

        int index = dictionary.IndexOfKey(theKey);
        if (index >= 0) {
        SomeClass value = dictionary.GetValueByIndex(index);
        dictionary.RemoveByIndex(index);
        // Do something with the value...
        }

        This would avoid double-lookup, and would support more scenarios than just one described above.

        If I'm not mistaken, dictionary is internally a hash table stored in a flat array, so an index should be able to act as a "pointer" into that array.

      • Qwertie commented  ·   ·  Flag as inappropriate

        In my project I created a "optionally-persistent" hastable which does what you want and other things too. It's called MMap<K,V> (i.e. mutable map; it can be converted to/from an immutable Map<K,V> in O(1) time.)

        In MMap<K,V>, GetAndRemove() removes the pair and gets its value, AddIfNotPresent() adds value only if the key is not already present, AddOrFind() gets the existing value, if any, adds a new value, if not, and optionally overwrites the existing value (all this in addition to the usual IDictionary interface). Also, it has an O(1) Clone method and, as I mentioned, a persistent immutable equivalent. Also, I made mutable and immutable set types based on the same data structure (in fact the map is based on the set, rather than the other way around.)

        It also has the "batch" operation AddRange(), and "persistent" operations Union(), Except(), Intersect(), Xor(), With(), WIthout(), all of which return a new map, leaving the original one unchanged. These are just for convenience though, they are not faster than the equivalent manual sequence of steps.

        These data structures and others are currently part of the Loyc project: https://sourceforge.net/projects/loyc/

        Preview: https://sourceforge.net/p/loyc/code/HEAD/tree/Src/Collections/Sets/MMap.cs

        Sadly its core operations are not as fast as Dictionary, but it is often more than half as fast as Dictionary. Methods like GetAndRemove() give you two operations for the price of one, so at least you might be able to break even, and you'll gain the benefits of a persistent hashtable if you ever need them.

      • Howard commented  ·   ·  Flag as inappropriate

        Why not just add an extension method?

        /// <summary>
        /// Try to remove an item from a Dictionary if it exists
        /// </summary>
        /// <param name="value">Object</param>
        /// <returns></returns>
        public static bool TryRemove<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, out TValue value)
        {
        if (!dict.ContainsKey(key))
        {
        value = default(TValue);
        return false;
        }
        else
        {
        value = dict[key];
        dict.Remove(key);
        return true;
        }
        }

      • David Kean commented  ·   ·  Flag as inappropriate

        Matt,

        Ryan wants to retrieve the value at the same time as removing, to reduce the double lookup. Really, the method's behavior is better described as TryGetAndRemove.

        David

      • David Kean commented  ·   ·  Flag as inappropriate

        Thanks for the great suggestion! We'll consider this for a future version.

        David Kean
        BCL Team

      • Sean Hanna commented  ·   ·  Flag as inappropriate

        As a workaround, you can always use ConcurrentDictionary<> instead.

        It would be nice to bring all the concurrent dictionary methods into Dictionary<> though, AddOrUpdate(), TryRemove, GetOrAdd(), etc..

      Feedback and Knowledge Base