Is there an IDictionary implementation that, on missing key, returns the default value instead of throwing?

前端 未结 15 1754
暗喜
暗喜 2020-11-27 04:00

The indexer into Dictionary throws an exception if the key is missing. Is there an implementation of IDictionary that instead will return de

相关标签:
15条回答
  • 2020-11-27 04:49

    This question helped to confirm that the TryGetValue plays the FirstOrDefault role here.

    One interesting C# 7 feature I would like to mention is the out variables feature, and if you add the null-conditional operator from C# 6 to the equation your code could be much more simple with no need of extra extension methods.

    var dic = new Dictionary<string, MyClass>();
    dic.TryGetValue("Test", out var item);
    item?.DoSomething();
    

    The downside of this is that you can't do everything inline like this;

    dic.TryGetValue("Test", out var item)?.DoSomething();
    

    If we'd need/want to do this we should code one extension method like Jon's.

    0 讨论(0)
  • 2020-11-27 04:50

    Indeed, that won't be efficient at all.

    You could always write an extension method:

    public static TValue GetValueOrDefault<TKey,TValue>
        (this IDictionary<TKey, TValue> dictionary, TKey key)
    {
        TValue ret;
        // Ignore return value
        dictionary.TryGetValue(key, out ret);
        return ret;
    }
    

    Or with C# 7.1:

    public static TValue GetValueOrDefault<TKey,TValue>
        (this IDictionary<TKey, TValue> dictionary, TKey key) =>
        dictionary.TryGetValue(key, out var ret) ? ret : default;
    

    That uses:

    • An expression-bodied method (C# 6)
    • An out variable (C# 7.0)
    • A default literal (C# 7.1)
    0 讨论(0)
  • 2020-11-27 04:52

    Carrying these extension methods can help..

    public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key)
    {
        return dict.GetValueOrDefault(key, default(V));
    }
    
    public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, V defVal)
    {
        return dict.GetValueOrDefault(key, () => defVal);
    }
    
    public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, Func<V> defValSelector)
    {
        V value;
        return dict.TryGetValue(key, out value) ? value : defValSelector();
    }
    
    0 讨论(0)
  • 2020-11-27 04:53

    Since .NET core 2.0 you can use:

    myDict.GetValueOrDefault(someKeyKalue)
    
    0 讨论(0)
  • 2020-11-27 04:54

    One could define an interface for the key-lookup function of a dictionary. I'd probably define it as something like:

    Interface IKeyLookup(Of Out TValue)
      Function Contains(Key As Object)
      Function GetValueIfExists(Key As Object) As TValue
      Function GetValueIfExists(Key As Object, ByRef Succeeded As Boolean) As TValue
    End Interface
    
    Interface IKeyLookup(Of In TKey, Out TValue)
      Inherits IKeyLookup(Of Out TValue)
      Function Contains(Key As TKey)
      Function GetValue(Key As TKey) As TValue
      Function GetValueIfExists(Key As TKey) As TValue
      Function GetValueIfExists(Key As TKey, ByRef Succeeded As Boolean) As TValue
    End Interface
    

    The version with non-generic keys would allow code that was using code using non-structure key types to allow for arbitrary key variance, which would not be possible with a generic type parameter. One should not be allowed to use a mutable Dictionary(Of Cat, String) as a mutable Dictionary(Of Animal, String) since the latter would allow SomeDictionaryOfCat.Add(FionaTheFish, "Fiona"). But there's nothing wrong with using a mutable Dictionary(Of Cat, String) as an immutable Dictionary(Of Animal, String), since SomeDictionaryOfCat.Contains(FionaTheFish) should be considered a perfectly well-formed expression (it should return false, without having to search the dictionary, for anything that isn't of type Cat).

    Unfortunately, the only way one will be able to actually use such an interface is if one wraps a Dictionary object in a class which implements the interface. Depending upon what you're doing, however, such an interface and the variance it allows might make it worth the effort.

    0 讨论(0)
  • 2020-11-27 04:55

    If you're using .Net Core, you can use the CollectionExtensions.GetValueOrDefault method. This is the same as the implementation provided in the accepted answer.

    public static TValue GetValueOrDefault<TKey,TValue> (
       this System.Collections.Generic.IReadOnlyDictionary<TKey,TValue> dictionary,
       TKey key);
    
    0 讨论(0)
提交回复
热议问题