What is the correct approach when trying to remove some items in ConcurrentDictionary

Is this better:

    public void Test()
    {

        ConcurrentDictionary<int, string> dictionary = new ConcurrentDictionary<int, string>();

        dictionary.TryAdd(0, "A");
        dictionary.TryAdd(1, "B");
        dictionary.TryAdd(2, "A");
        dictionary.TryAdd(3, "D");

        foreach (var item in dictionary)
        {
            string foundItem;

            if (dictionary.TryGetValue(item.Key, out foundItem))
            {
                if (foundItem == "A")
                {
                    if (dictionary.TryRemove(item.Key, out foundItem))
                    {
                        // Success
                    }
                }
            }
        }

    }  

Than this?:

    public void Test2()
    {

        ConcurrentDictionary<int, string> dictionary = new ConcurrentDictionary<int, string>();

        dictionary.TryAdd(0, "A");
        dictionary.TryAdd(1, "B");
        dictionary.TryAdd(2, "A");
        dictionary.TryAdd(3, "D");

        foreach (var item in dictionary)
        {
            string foundItem;

            if (item.Value == "A")
            {
                if (dictionary.TryRemove(item.Key, out foundItem))
                {
                    // Success
                }
            }
        }

    }  

This method will be accessed by multiple thread.

My confusion is, whenever I want to remove an item, I try to get it first, then remove it. But in the first place, I have used foreach loop, meaning I have already get the item. Any idea would be appreciated.

Jon Skeet
people
quotationmark

I don't see any benefit in the first approach. I'd just use LINQ to find the items though:

foreach (var entry in dictionary.Where(e => e.Value == "A"))
{
    string ignored;
    // Do you actually need to check the return value?
    dictionary.TryRemove(entry.Key, out ignored);
}

Of course, you need to consider what you want to happen if another thread adds a new entry with value "A" or updates an existing entry (possibly to make the value "A", possibly to make the value not-"A" while you're iterating... does it matter to you whether or not that entry is removed? It's not guaranteed what will happen. (The iterator doesn't take a snapshot, but isn't guaranteed to return entirely up-to-date data either.)

You may want to check that the value you've removed really is "A" by checking the variable I've called ignored afterwards. It really depends on your context. When you've got multiple threads modifying the map, you need to think that anything can happen at any time - within the operations that your code actually performs.

There's also the fact that you're effectively having to trawl through the whole dictionary... are you looking up by key elsewhere?

people

See more on this question at Stackoverflow