Which mechanism is a better way to extend Dictionary to deal with missing keys and why?

后端 未结 3 1317
一整个雨季
一整个雨季 2021-01-04 00:48

There is a minor annoyance I find myself with a lot - I have a Dictionary that contains values that may or may not be there.

So norm

相关标签:
3条回答
  • 2021-01-04 01:20

    When naming an extension method intended to replace an existing method, I tend to add to the method name for specificity rather than shortening it:

    GetValueOrDefault(...)
    

    As for the ForgivingDictionary, you can constrain TKey so that it can't be a value type. However, if you must deal with value types in it, you're going to return something for a value type and the best option is to return default(TKey) since you can't return null.

    Honestly, I'd go with the extension method.

    Edit: GetValueOrDefault(), of course, wouldn't add to the dictionary if it didn't find the key. I would just return a default value if it wasn't found, because that's how it's named. If one wanted it to insert as well, a good name would be GetValueOrInsertDefault().

    0 讨论(0)
  • 2021-01-04 01:20

    I'm unable to infer from your question what should be done when a key is not found. I can imagine nothing should be done in that case, but I can also imagine the opposite. Anyway, an elegant alternative for a series of these TryGetValue-statements you describe, is using one of the following extension methods. I have provided two options, depending on whether something should be done or not when the dictionary does not contain the key:

    /// <summary> Iterates over all values corresponding to the specified keys, 
    ///for which the key is found in the dictionary. </summary>
    public static IEnumerable<TValue> TryGetValues<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, IEnumerable<TKey> keys)
    {
        TValue value;
        foreach (TKey key in keys)
            if (dictionary.TryGetValue(key, out value))
                yield return value;
    }
    
    /// <summary> Iterates over all values corresponding to the specified keys, 
    ///for which the key is found in the dictionary. A function can be specified to handle not finding a key. </summary>
    public static IEnumerable<TValue> TryGetValues<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, IEnumerable<TKey> keys, Action<TKey> notFoundHandler)
    {
        TValue value;
        foreach (TKey key in keys)
            if (dictionary.TryGetValue(key, out value))
                yield return value;
            else
                notFoundHandler(key);                        
    }
    

    Example code on how to use this is:

    TKey[] keys = new TKey{...};
    foreach(TValue value in dictionary.TryGetValues(keys))
    {
        //some action on all values here
    }
    
    0 讨论(0)
  • 2021-01-04 01:29

    Or perhaps

    public static TValue TryGet<TKey, TValue>(this Dictionary<TKey, TValue> input, 
                                                       TKey key)
    {
    
         return input.ContainsKey(key) ? input[key] : *some default value*;
    
    }
    
    0 讨论(0)
提交回复
热议问题