IDictionary How to get the removed item value while removing [duplicate]
Asked Answered
R

2

6

I would like to know if it is possible to remove an IDictionary item by its key and in the same time get its actual value that has been removed?

Example

something like:

Dictionary<string,string> myDic = new Dictionary<string,string>();
myDic["key1"] = "value1";

string removed;
if (nameValues.Remove("key1", out removed)) //No overload for this...
{
    Console.WriteLine($"We have just remove {removed}");
}

Output

//We have just remove value1
Reedy answered 28/8, 2018 at 17:1 Comment(6)
No, there isn't. What happens when the key does not exist?Jacobsen
@RonBeyer Remove returns false when the key does not exist.Carniola
@JonathonChase I know that, but what does the out removed then contain? null? default(T)?Jacobsen
@RonBeyer I've updated my question, my current design is ok with null.Reedy
@RonBeyer I'd expect default(T) as with the TryXYZ pattern, but you're right it needs to be defined.Carniola
Closing the question with duplicate link. The original question has an answer today (.NET Core 2.0 onwards).Jenelljenelle
D
10

Normal dictionaries don't have this functionality as an atomic operation but a ConcurrentDictionary<TKey,TValue> does.

ConcurrentDictionary<string,string> myDic = new ConcurrentDictionary<string,string>();
myDic["key1"] = "value1";

string removed;
if (myDic.TryRemove("key1", out removed))
{
    Console.WriteLine($"We have just remove {removed}");
}

You could write an extension method for a normal dictionary to implement this but if you are concerned about it being atomic a ConcurrentDictionary is probably more correct for your use case.

Downs answered 28/8, 2018 at 17:6 Comment(0)
J
6

You could write an extension method for this:

public static class DictionaryExtensions
{
    public static bool TryRemove<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, out TValue value)
    {
        if (dict.TryGetValue(key, out value))
            return dict.Remove(key);
        else
            return false;
    }
}

This will attempt to get the value and if it exists, will remove it. Otherwise you should use a ConcurrentDictionary as the other answer said.

Jacobsen answered 28/8, 2018 at 17:13 Comment(7)
value = default(TValue);Perigordian
This is definitely a personal preference but it might be a little easier to follow if the default assignment happened before the return false since that is the only time it is ever used.Downs
@RufusL 7.3 can infer it, it's not needed in this case.Jacobsen
@RufusL I was actually going to ask about that too. I am surprised i missed that feature, thank you for the heads up!Downs
@RonBeyer Good to know, I guess I'm still a little old school.. :)Perigordian
@RufusL You can set a value in an if and an else because both possible branches are covered. In this case you dont need it at all because no matter what the value is assigned by the TryGetValueDowns
Cool, so the whole thing could be reduced to return dict.TryGetValue(key, out value) && dict.Remove(key);Perigordian

© 2022 - 2024 — McMap. All rights reserved.