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.

270 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Ryan RastedtRyan Rastedt shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    8 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • QwertieQwertie 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.

      • Anonymous 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 KeanDavid 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 KeanDavid Kean commented  ·   ·  Flag as inappropriate

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

        David Kean
        BCL Team

      • Sean HannaSean 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