The indexer into Dictionary
throws an exception if the key is missing. Is there an implementation of IDictionary
that instead will return de
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.
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:
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();
}
Since .NET core 2.0 you can use:
myDict.GetValueOrDefault(someKeyKalue)
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.
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);