5

In Python, if I have a dict, and I want to get a value from a dict where the key might not be present I'd do something like:

lookupValue = somedict.get(someKey, someDefaultValue)

where, if someKey is not present, then someDefaultValue is returned.

In C#, there's TryGetValue() which is kinda similar:

var lookupValue;
if(!somedict.TryGetValue(someKey, lookupValue))
    lookupValue = someDefaultValue;

One gotcha with this though is that if someKey is null then an exception gets thrown, so you put in a null-check:

var lookupValue = someDefaultValue;
if (someKey != null && !somedict.TryGetValue(someKey, lookupValue))
    lookupValue = someDefaultValue;

Which, TBH, is icky (3 lines for a dict lookup?) Is there a more concise (ie 1-line) way that is much like Python's get()?

Adam Parkin
  • 14,883
  • 13
  • 57
  • 81
  • Afaik there is no such way. But you can always define your own extension to wrap these three lines. Or you could use ternary to have a one-liner, but it is not that different from your approach – Andrei Jan 29 '15 at 17:02
  • I think ternary still wouldn't be a one liner as you'd have to declare ```lookupValue``` before the ```TryGetValue``` right? – Adam Parkin Jan 29 '15 at 17:11
  • `var lookupValue = someKey != null ? somedict.TryGetValue(someKey, someDefaultValue) : someDefaultValue;` unless I am missing something. But again, that does look nice at all – Andrei Jan 29 '15 at 17:39
  • Note that if the key is not found in the dictionary `TryGetValue` will set the `out` `value` parameter to it's default, overriding any value the variable passed in was previously set to. – juharr Jan 29 '15 at 17:57
  • @PrestonGuillot and @Andrei `TryGetValue` returns a bool, so it cannot be used in the way you have stated it. Instead it should be `var lookupValue = key != null && dic.TryGetValue(key, tempValue) ? tempValue : defaultValue;` – juharr Jan 29 '15 at 18:29
  • 1
    @AdamParkin Yes, you are absolutely correct that you have to declare the out value you pass to `TryGetValue` first. You could instead do this for a one-liner though `var value = key != null && dic.ContainsKey(key) ? dic[key] : defaultValue;` This is less efficient than `TryGetValue` because it does the lookup twice when the key is in the dictionary. – juharr Jan 29 '15 at 18:32
  • 1
    Sure, but dict keys are hashed, so it's still constant time (ie O(1) + O(1) == O(1)) right? – Adam Parkin Jan 29 '15 at 22:06
  • 1
    @AdamParkin True, the complexity does not change, but doing something twice always takes longer than doing it once. – juharr Jan 30 '15 at 17:16
  • histogram[c] = histogram.ContainsKey(c) ? histogram[c] + 1 : 1; – Paul Williams Dec 10 '19 at 11:01

2 Answers2

6

Here's the correct way to use TryGetValue. Note that you can not set the return value to the default before calling TryGetValue and just return it as TryGetValue will reset it to it's default value if the key is not found.

public static TValue GetOrDefault<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary, 
    TKey key, 
    TValue defaultValue)
{
    TValue value;
    if(key == null || !dictionary.TryGetValue(key, out value))
        return defaultValue;
    return value;
}

Of course you might actually want an exception if key is null since that is always an invalid key for a dictionary.

This can now be simplified to the following with C# 7.0 inline out variable declarations.

return key ==  null || !dictionary.TryGetValue(key, out var value)
    ? defaultValue
    : value;
juharr
  • 30,127
  • 4
  • 48
  • 88
0

TryGetValue is not the method you are looking for. This method returns a boolean value. True if it finds the key and false if it does not.Anf if a key is found, it will set the value to the variable you have choosen. The method you want, does not exist in Dictonary class. So you have two options to solve the problem:

  1. Check if it exists or not:

    var value;
    if (somedic.TryGetValue("key", out value))
       lookupValue  = value;
    else
       lookupValue = defaultValue;
    
  2. Create your own method as is shown in this blog.

  • You also have to check that the key is not null, unless you have set the key type as a non-nullable struct, (unless you want to throw an exception when the key is null). – juharr Jan 29 '15 at 18:15
  • Yeah, right. So best to implement it as shown in the blog. – alejoaldana Jan 29 '15 at 18:23
  • The blog doesn't test the key for null either. That method would throw an exception for a null key, but that may or may not be the correct course of action, but the OP seems to want the default value if the key is null. – juharr Jan 29 '15 at 18:26