Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# optimal IDictionary usage for lookup with possibility of not found

Let's say I have a method as follows:

internal MyClass GetValue(long key)
{
  if (_myDictionary.ContainsKey(key))
    return _myDictionary[key];

  return null; // Not found
}

IDictionary<long,MyClass> _myDictionary=...

But the above code has two lookups in the dictionary:

  1. The test for the existance of the key
  2. The actual retrieval of the value

Is there a more optimal way to phrase such a function, so that only one lookup is performed, but the case of "not found" is still handled via a null return (i.e., not via a not found exception)?

For example, it would have been nice if the lookup for the key returned some sort of iterator that could be used to retrieve the value or an invalid iterator if the value was not found as is done in C++. Perhaps C# has a better way of doing this given its language features.

like image 213
Michael Goldshteyn Avatar asked Feb 28 '12 15:02

Michael Goldshteyn


3 Answers

The TryGetValue method was designed for precisely this scenario - to avoid the two lookup operations.

This method combines the functionality of the ContainsKey method and the Item property.

If the key is not found, then the value parameter gets the appropriate default value for the value type TValue.

[...] Use the TryGetValue method if your code frequently attempts to access keys that are not in the dictionary. Using this method is more efficient than catching the KeyNotFoundException thrown by the Item property.

internal MyClass GetValue(long key)
{
    MyClass maybeValue;

    // Normally, one would inspect the return value of this method
    // but in this case, it's not necessary since a failed lookup
    // will set the out argument to default(valType), which is null
    // for a reference type - exactly what you want.
   _myDictionary.TryGetValue(key, out maybeValue);

    return maybeValue; 
}
like image 155
Ani Avatar answered Nov 03 '22 08:11

Ani


typing up SPFiredrakes idea ...

public static class Extensions
{ 
    public static TValue GetValueOrDefault<TKey, TValue>(
            this IDictionary<Tkey, TValue> iDictionary, Tkey key)
    {
        TValue result;
        return iDictionary.TryGetValue(key, out result) ? result : default(TValue)
    }
}

used like this

var d = new Dictionary<long, SomeType> 
    {{1, new SomeType()}, {42, new SomeType()}, ...}

var value1 = d.GetValueOrDefault(1);
var value42 = d.GetValueOrDefault(42);
var valueX = d.GetValueOrDefault(10);

Of course, you should now check to see if your values are null, which may be why the .Net team omitted this feature.

like image 23
Jodrell Avatar answered Nov 03 '22 10:11

Jodrell


You should use TryGetValue instead - it uses a single lookup.

internal MyClass GetValue(long key) {
    MyClass  res = null;
    _myDictionary.TryGetValue(key, out res)
    return res;
}

The call is short enough to use "inline", without adding a wrapper function. TryGetValue returns a bool indicating if the lookup has been successful or not.

like image 38
Sergey Kalinichenko Avatar answered Nov 03 '22 09:11

Sergey Kalinichenko