.NET Dictionary: get existing value or create and add new value - c#

I often find myself creating a Dictionary with a non-trivial value class (e.g. List), and then always writing the same code pattern when filling in data.
For example:
var dict = new Dictionary<string, List<string>>();
string key = "foo";
string aValueForKey = "bar";
That is, I want to insert "bar" into the list that corresponds to key "foo", where key "foo" might not be mapped to anything.
This is where I use the ever-repeating pattern:
List<string> keyValues;
if (!dict.TryGetValue(key, out keyValues))
dict.Add(key, keyValues = new List<string>());
keyValues.Add(aValueForKey);
Is there a more elegant way of doing this?
Related questions that don't have answers to this question:
Is there an IDictionary implementation that returns null on missing key instead of throwing?
Find-or-insert with only one lookup in c# dictionary
Dictionary returning a default value if the key does not exist

We have a slightly different take on this, but the effect is similar:
public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
where TValue : new()
{
if (!dict.TryGetValue(key, out TValue val))
{
val = new TValue();
dict.Add(key, val);
}
return val;
}
Called:
var dictionary = new Dictionary<string, List<int>>();
List<int> numbers = dictionary.GetOrCreate("key");
It makes use of the generic constraint for public parameterless constructors: where TValue : new().
To help with discovery, unless the extension method is quite specific to a narrow problem, we tend to place extension methods in the namespace of the type they are extending, in this case:
namespace System.Collections.Generic
Most of the time, the person using the type has the using statement defined at the top, so IntelliSense would also find the extension methods for it defined in your code.

As with so many programming problems, when you find yourself doing something a lot, refactor it into a method:
public static void MyAdd<TKey, TCollection, TValue>(
this Dictionary<TKey, TCollection> dictionary, TKey key, TValue value)
where TCollection : ICollection<TValue>, new()
{
TCollection collection;
if (!dictionary.TryGetValue(key, out collection))
{
collection = new TCollection();
dictionary.Add(key, collection);
}
collection.Add(value);
}

If you use .Net Core you can use Dictionary<>.TryAdd().
var dict = new Dictionary<string, string>();
dict.TryAdd("foo", "bar"); // returns bool whether it added or not feel free to ignore.
var myValue = dict["foo"];

Here is a solution in case the constructor requires a parameter.
public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue> createNew)
{
if (!dict.TryGetValue(key, out var val))
{
val = createNew();
dict.Add(key, val);
}
return val;
}
Simple to use:
MyDict.GetOrCreate(si.Id, createNew: () => new ObjectKnowingItsId(si.Id))

For further readers, here are some extensions in every flavour I thought fit. You could also do something with an out parameter if you need to check if you have added a value but i think you can use containskey or something already for that.
You can use GetOrAddNew to retrieve an item, or create and add it to the dict. You can use the various overloads of GetOrAdd to add a new value. This could be the default so e.g. NULL or 0 but you can also provide a lambda to construct an object for you, with any kind of constructor arguments you'd like.
var x = new Dictionary<string, int>();
var val = x.GetOrAdd("MyKey", (dict, key) => dict.Count + 2);
var val2 = x.GetOrAdd("MyKey", () => Convert.ToInt32("2"));
var val3 = x.GetOrAdd("MyKey", 1);
/// <summary>
/// Extensions for dealing with <see cref="Dictionary{TKey,TValue}"/>
/// </summary>
public static class DictionaryExtensions
{
public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default)
where TValue : new()
=> dict.GetOrAdd(key, (values, innerKey) => EqualityComparer<TValue>.Default.Equals(default(TValue), defaultValue) ? new TValue() : defaultValue);
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default)
=> dict.GetOrAdd(key, (values, innerKey) => defaultValue);
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue> valueProvider)
=> dict.GetOrAdd(key, (values, innerKey) => valueProvider());
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> valueProvider)
=> dict.GetOrAdd(key, (values, innerKey) => valueProvider(key));
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<IDictionary<TKey, TValue>, TKey, TValue> valueProvider)
{
if (dict == null) throw new ArgumentNullException(nameof(dict));
if (key == null) throw new ArgumentNullException(nameof(key));
if (valueProvider == null) throw new ArgumentNullException(nameof(valueProvider));
if (dict.TryGetValue(key, out var foundValue))
return foundValue;
dict[key] = valueProvider(dict, key);
return dict[key];
}
}

And what about this?
var keyValues = dictionary[key] = dictionary.ContainsKey(key) ? dictionary[key] : new List<string>();
keyValues.Add(aValueForKey);

Slight twist
Had a special need that was a literal match to the question, but maybe not its intent. For this case, getting the value was expensive (reflection) and only wanted to generate the value once, to populate the dictionary for caching. Building off #adam-houldsworth answer, the value argument was modified into a delegate.
public static TValue GetOrCreate<TKey, TValue>(
this IDictionary<TKey, TValue> self,
TKey key,
Func<TValue> getValue)
{
if (self == null)
{
throw new ArgumentNullException(nameof(self));
}
else if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
else if (!self.ContainsKey(key))
{
self[key] = getValue() ;
}
return self[key];
}
Usage
var assemblyName = callingAssemblies.GetOrCreate
(
path,
() => Assembly.GetCallingAssembly().GetName().Name
);

Ok, different approach:
public static bool TryAddValue<TKey,TValue>(this System.Collections.Generic.IDictionary<TKey,List<TValue>> dictionary, TKey key, TValue value)
{
// Null check (useful or not, depending on your null checking approach)
if (value == null)
return false;
List<TValue> tempValue = default(List<TValue>);
try
{
if (!dictionary.TryGetValue(key, out tempValue))
{
dictionary.Add(key, tempValue = new List<TValue>());
}
else
{
// Double null check (useful or not, depending on your null checking approach)
if (tempValue == null)
{
dictionary[key] = (tempValue = new List<TValue>());
}
}
tempValue.Add(value);
return true;
}
catch
{
return false;
}
}
In this way you have to "try to add" your value to a generic List of (obviously generalizable to a generic collection), null checking and trying to get existing key/values in your Dictionary.
Usage and example:
var x = new Dictionary<string,List<string>>();
x.TryAddValue("test", null); // return false due to null value. Doesn't add the key
x.TryAddValue("test", "ok"); // it works adding the key/value
x.TryAddValue("test", "ok again"); // it works adding the value to the existing list
Hope it helps.

I am missing the GetOrAdd for Dictionary, that does exist for ConcurrentDictionary.
ConcurrentDictionary<int,Guid> Conversion = new ConcurrentDictionary<int, Guid>();
List<int> before = new List<int> { 1, 2, 1, 3 };
List<Guid> after = before.Select(x => Conversion.GetOrAdd(x, Guid.NewGuid())).ToList();
This code will generate Guids for each number. Ending up converting both 1's in before to the same Guid.
In your case:
ConcurrentDictionary<int, List<String>> dict;
keyValues = dict.GetOrAdd(key, new List<String>());
keyValues.Add(aValueForKey);

using System.Runtime.InteropServices;
public static TValue GetOrCreate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, Func<TValue> valueProvider)
where TKey: notnull
{
ref var value = ref CollectionsMarshal.GetValueRefOrAddDefault(dictionary, key, out bool exists);
if (!exists) value = valueProvider.Invoke();
return value!;
}
public static TValue GetOrCreate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
where TKey: notnull
=> GetOrCreate(dictionary, key, () => value);
public static TValue GetOrCreate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
where TKey: notnull
where TValue : new()
=> GetOrCreate(dictionary, key, new TValue());
To avoid duplicate hash lookups.
You can find more info here.

ConcurrentDictionary.GetOrAdd does exactly what is being asked.
Initialization
ConcurrentDictionary<string, List<string>> dict = new();
Usage
var list = dict.GetOrAdd(key, _ => new List<string>());
Notice how we are using a factory method to create a new list as-need. This prevents pre-allocating a list on each call to GetOrAdd.

Related

Covariance on dictionary key

Assuming one has a method producing IReadOnlyDictionary<DerivedType, object>, how does one provide this object to a method taking IReadOnlyDictionary<BaseType, object>? Why does casting not work?
IReadOnlyDictionary<TKey, TValue> does not have covariant parameters for two reasons. First, TKey cannot be covariant because it is also used in an input position (in ContainsKey), and both TKey and TValue cannot be covariant because it also implements IEnumerable<KeyValuePair<TKey, TValue>> and KeyValuePair<TKey, TValue> is a value type and thus invariant.
Fortunately, even though the runtime cannot cast between the types, it is easy to adapt one to the other. First, if the underlying collection is actually a Dictionary<DerivedType, object>, this is one of the cases when one could inherit from Dictionary:
class BaseKeyDictionary<TBaseKey, TKey, TValue> : Dictionary<TKey, TValue>, IReadOnlyDictionary<TBaseKey, TValue> where TKey : class, TBaseKey
{
TValue IReadOnlyDictionary<TBaseKey, TValue>.this[TBaseKey key] => key is TKey key2 ? this[key2] : throw new KeyNotFoundException();
IEnumerable<TBaseKey> IReadOnlyDictionary<TBaseKey, TValue>.Keys => ((IReadOnlyDictionary<TKey, TValue>)this).Keys;
IEnumerable<TValue> IReadOnlyDictionary<TBaseKey, TValue>.Values => ((IReadOnlyDictionary<TKey, TValue>)this).Values;
int IReadOnlyCollection<KeyValuePair<TBaseKey, TValue>>.Count => Count;
bool IReadOnlyDictionary<TBaseKey, TValue>.ContainsKey(TBaseKey key)
{
return key is TKey key2 ? ContainsKey(key2) : false;
}
IEnumerator<KeyValuePair<TBaseKey, TValue>> IEnumerable<KeyValuePair<TBaseKey, TValue>>.GetEnumerator()
{
foreach(var pair in this)
{
yield return new KeyValuePair<TBaseKey, TValue>(pair.Key, pair.Value);
}
}
bool IReadOnlyDictionary<TBaseKey, TValue>.TryGetValue(TBaseKey key, out TValue value)
{
if(key is TKey key2) return TryGetValue(key2, out value);
value = default;
return false;
}
}
And, if one does not have access to the underlying type of the dictionary, it is always possible to create a wrapper for it to implement the interface via the original object:
class BaseKeyDictionaryWrapper<TBaseKey, TKey, TValue> : IReadOnlyDictionary<TBaseKey, TValue> where TKey : class, TBaseKey
{
readonly IReadOnlyDictionary<TKey, TValue> dict;
public BaseKeyDictionaryWrapper(IReadOnlyDictionary<TKey, TValue> dict)
{
this.dict = dict;
}
TValue IReadOnlyDictionary<TBaseKey, TValue>.this[TBaseKey key] => key is TKey key2 ? dict[key2] : throw new KeyNotFoundException();
IEnumerable<TBaseKey> IReadOnlyDictionary<TBaseKey, TValue>.Keys => dict.Keys;
IEnumerable<TValue> IReadOnlyDictionary<TBaseKey, TValue>.Values => dict.Values;
int IReadOnlyCollection<KeyValuePair<TBaseKey, TValue>>.Count => dict.Count;
bool IReadOnlyDictionary<TBaseKey, TValue>.ContainsKey(TBaseKey key)
{
return key is TKey key2 ? dict.ContainsKey(key2) : false;
}
IEnumerator<KeyValuePair<TBaseKey, TValue>> IEnumerable<KeyValuePair<TBaseKey, TValue>>.GetEnumerator()
{
foreach(var pair in dict)
{
yield return new KeyValuePair<TBaseKey, TValue>(pair.Key, pair.Value);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IReadOnlyDictionary<TBaseKey, TValue>)this).GetEnumerator();
}
bool IReadOnlyDictionary<TBaseKey, TValue>.TryGetValue(TBaseKey key, out TValue value)
{
if(key is TKey key2) return dict.TryGetValue(key2, out value);
value = default;
return false;
}
}

How to Cast a generic type of any type to another type

I am trying to create a recursive method that makes a deep copy of a dictionary to any length by checking if the hash value is another dictionary and then copy it again before hashing it.
I have tried this and the compiler rejects the line in Blockquote, who can find the error?
private Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(Dictionary<TKey,
TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (dict.Value is Dictionary<Object, Object>)
{
retDict[dict.Key] = NestedCopy(dict.Value asDictionary<object, object>);
}
}
return retDict;
}
retDict[dict.Key] = NestedCopy(dict.Value asDictionary);
This is the error line,
It says it cannot implicitly convert from Dictionary to TValue
Dictionary<string, Dictionary<string, int>> dict;
var newDict = NestedCopy(newDict);
//I expect newDict to be a copy of dict
There is no way for the compiler to statically infer the recursive call. So, you gonna need reflection or at least let the compiler do the reflection for you by using the dynamic keyword:
private Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
retDict[dict.Key] = (TValue)NestedCopy((dynamic)dict.Value);
}
else
{
retDict[dict.Key] = dict.Value;
}
}
return retDict;
}
The more explicit code with hand-made reflection could look as follows:
private static Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var reflectionMethod = typeof(Program).GetMethod("NestedCopy", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
var methodToCall = reflectionMethod.MakeGenericMethod(typeof(TValue).GetGenericArguments());
retDict[dict.Key] = (TValue)methodToCall.Invoke(null, new object[] { dict.Value });
}
else
{
retDict[dict.Key] = dict.Value;
}
}
return retDict;
}
Note this assumes the method to belong to Program class and I made it static since its not using any context.
Since the decision for the if-else doesn't depend on dict.Value but only on the TValue that stays the same throughout the method, you could also move the condition out of the loop:
private static Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
Func<TValue, TValue> clone;
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
clone = v => NestedCopy((dynamic)v);
}
else
{
clone = v => v;
}
foreach (var dict in nestedDict)
{
retDict[dict.Key] = clone(dict.Value);
}
return retDict;
}
I think you don't need to recursive it, it relies on you how to implement the TValue.Clone method.
private Dictionary<TKey, TValue> CloneDictionary<TKey, TValue>(Dictionary<TKey, TValue> sourceDic)
where TValue : ICloneable
{
var ret = new Dictionary<TKey, TValue>(sourceDic.Count, sourceDic.Comparer);
foreach (KeyValuePair<TKey, TValue> entry in sourceDic)
{
ret.Add(entry.Key, (TValue)entry.Value.Clone());
}
return ret;
}

Do I need a lock in AddOrUpdate of a concurrent dictionary?

in my class I have
public static ConcurrentDictionary<string, HashSet<string>> ConnectedUserConnections = new ConcurrentDictionary<string, HashSet<string>>();
When adding or updating, should I update via:
ConnectedUserConnections.AddOrUpdate(userId, new HashSet<string>(), (key, existingVal) =>
{
existingVal.Add(connectionId);
return existingVal;
});
or
ConnectedUserConnections.AddOrUpdate(userId, new HashSet<string>(), (key, existingVal) =>
{
lock(ConnectedUserConnections)
{
existingVal.Add(connectionId);
return existingVal;
}
});
Many thanks all.
By looking at the public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) from the reference source,
while (true)
{
TValue oldValue;
if (TryGetValue(key, out oldValue))
//key exists, try to update
{
newValue = updateValueFactory(key, oldValue);
if (TryUpdate(key, newValue, oldValue))
There is no lock until the TryGetValue, so if there is already a value for key, multiple threads could arrive at the TryGetValue, execute it, return true, execute the updateValueFactory (your method) at the same time and try adding existingVal.Add(connectionId);...
So yes, you do need a lock.

C# easy way to add keys and values to nested dictionary?

Is there an easy way to add value to a nested dictionary. I am looking for a way to replace the following type of code with an easy one.
if (NestedDictionary.ContainsKey(key1))
{
if (NestedDictionary[key1].ContainsKey(key2))
{
if (NestedDictionary[key1][key2].ContainsKey(key3))
{
//do nothing
}
else
{
NestedDictionary[key1][key2].Add(key3,1);
}
}
else
{
NestedDictionary[key1].Add(key2, new Dictionary<int,int>() { { key3, 1 } });
}
}
else
{
NestedDictionary.Add(key1, new Dictionary<int, Dictionary<int,int>>() { { key2, new Dictionary<int,int>() { { key3, 1} } } });
}
We can write a GetOrAdd method that either gets the value for a particular key if it's there, or assigns a new value if there is none:
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary,
TKey key,
TValue newValue)
{
TValue oldValue;
if (dictionary.TryGetValue(key, out oldValue))
return oldValue;
else
{
dictionary.Add(key, newValue);
return newValue;
}
}
(Note you can create a second overload that accepts a Func<TValue> instead of a TValue, which is useful if the value is either expensive to create or causes side effects.)
Now this problem becomes very easy:
var dictionary = new Dictionary<int, Dictionary<int, string>>();
dictionary.GetOrAdd(key1, new Dictionary<int, string>())[key2] = value;
We get the inner dictionary for the outer key, or create a new blank one if it doesn't exist, and then we assign the new value to the dictionary returned. Note that the indexer will add an item if it doesn't exist or update the item if it already does.
This of course scales reasonably well as we add dimensions as well:
var dictionary = new Dictionary<int, Dictionary<int, Dictionary<int, string>>>();
dictionary.GetOrAdd(key1, new Dictionary<int, Dictionary<int, string>>())
.GetOrAdd(key2, new Dictionary<int, string>())[key3] = value;
In our case we are actually fine always adding the default value of TValue using our GetOrAdd method, so if we add an overload to support that:
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dictionary,
TKey key)
where TValue : new()
{
TValue oldValue;
if (dictionary.TryGetValue(key, out oldValue))
return oldValue;
else
{
var newValue = new TValue();
dictionary.Add(key, newValue);
return newValue;
}
}
It simplifies the code even more:
dictionary.GetOrAdd(key1).GetOrAdd(key2)[key3] = value;
And if you really end up doing this particular operation a lot, you can just create a method to do the whole thing:
public static void AddMany<TKey1, TKey2, TKey3, TValue>(
this Dictionary<TKey1, Dictionary<TKey2, Dictionary<TKey3, TValue>>> dictionary,
TKey1 key1,
TKey2 key2,
TKey3 key3,
TValue newValue)
{
dictionary.GetOrAdd(key1).GetOrAdd(key2)[key3] = newValue;
}
Allowing you to write:
dictionary.AddMany(key1, key2, key3, value);
Of course, you need to create a new AddMany overload for each number of keys you want to support, and it has to be a number known at compile time, but that does appear to be the case in your example.
You can simplify the inner part:
if (NestedDictionary.ContainsKey(key1))
{
if (NestedDictionary[key1].ContainsKey(key2))
{
NestedDictionary[key1][key2][key3]=1;
}
else
{
NestedDictionary[key1].Add(key2, new Dictionary<int,int>() { { key3, 1 } });
}
}
else
{
NestedDictionary.Add(key1, new Dictionary<int, Dictionary<int,int>>() { { key2, new Dictionary<int,int>() { { key3, 1} } } });
}
But that's about it.
But what's the point of the structure? You only ever add a constant value (1) to the innermost dictionary, so there's no real "value" there. You might as well use a List<string> at that level.

Dictionary returning a default value if the key does not exist [duplicate]

This question already has answers here:
Is there an IDictionary implementation that, on missing key, returns the default value instead of throwing?
(17 answers)
Closed 9 years ago.
I find myself using the current pattern quite often in my code nowadays
var dictionary = new Dictionary<type, IList<othertype>>();
// Add stuff to dictionary
var somethingElse = dictionary.ContainsKey(key) ? dictionary[key] : new List<othertype>();
// Do work with the somethingelse variable
Or sometimes
var dictionary = new Dictionary<type, IList<othertype>>();
// Add stuff to dictionary
IList<othertype> somethingElse;
if(!dictionary.TryGetValue(key, out somethingElse) {
somethingElse = new List<othertype>();
}
Both of these ways feel quite roundabout. What I really would like is something like
dictionary.GetValueOrDefault(key)
Now, I could write an extension method for the dictionary class that does this for me, but I figured that I might be missing something that already exists. SO, is there a way to do this in a way that is more "easy on the eyes" without writing an extension method to dictionary?
TryGetValue will already assign the default value for the type to the dictionary, so you can just use:
dictionary.TryGetValue(key, out value);
and just ignore the return value. However, that really will just return default(TValue), not some custom default value (nor, more usefully, the result of executing a delegate). There's nothing more powerful built into the framework. I would suggest two extension methods:
public static TValue GetValueOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultValue)
{
return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
}
public static TValue GetValueOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
Func<TValue> defaultValueProvider)
{
return dictionary.TryGetValue(key, out var value) ? value : defaultValueProvider();
}
(You may want to put argument checking in, of course :)
I do favor extension methods, but here's a simple class I use from time to time to handle dictionaries when I need default values.
I wish this were just part of the base Dictionary class.
public class DictionaryWithDefault<TKey, TValue> : Dictionary<TKey, TValue>
{
TValue _default;
public TValue DefaultValue {
get { return _default; }
set { _default = value; }
}
public DictionaryWithDefault() : base() { }
public DictionaryWithDefault(TValue defaultValue) : base() {
_default = defaultValue;
}
public new TValue this[TKey key]
{
get {
TValue t;
return base.TryGetValue(key, out t) ? t : _default;
}
set { base[key] = value; }
}
}
Beware, however. By subclassing and using new (since override is not available on the native Dictionary type), if a DictionaryWithDefault object is upcast to a plain Dictionary, calling the indexer will use the base Dictionary implementation (throwing an exception if missing) rather than the subclass's implementation.
I created a DefaultableDictionary to do exactly what you are asking for!
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace DefaultableDictionary {
public class DefaultableDictionary<TKey, TValue> : IDictionary<TKey, TValue> {
private readonly IDictionary<TKey, TValue> dictionary;
private readonly TValue defaultValue;
public DefaultableDictionary(IDictionary<TKey, TValue> dictionary, TValue defaultValue) {
this.dictionary = dictionary;
this.defaultValue = defaultValue;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
return dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public void Add(KeyValuePair<TKey, TValue> item) {
dictionary.Add(item);
}
public void Clear() {
dictionary.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item) {
return dictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
dictionary.CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<TKey, TValue> item) {
return dictionary.Remove(item);
}
public int Count {
get { return dictionary.Count; }
}
public bool IsReadOnly {
get { return dictionary.IsReadOnly; }
}
public bool ContainsKey(TKey key) {
return dictionary.ContainsKey(key);
}
public void Add(TKey key, TValue value) {
dictionary.Add(key, value);
}
public bool Remove(TKey key) {
return dictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value) {
if (!dictionary.TryGetValue(key, out value)) {
value = defaultValue;
}
return true;
}
public TValue this[TKey key] {
get
{
try
{
return dictionary[key];
} catch (KeyNotFoundException) {
return defaultValue;
}
}
set { dictionary[key] = value; }
}
public ICollection<TKey> Keys {
get { return dictionary.Keys; }
}
public ICollection<TValue> Values {
get
{
var values = new List<TValue>(dictionary.Values) {
defaultValue
};
return values;
}
}
}
public static class DefaultableDictionaryExtensions {
public static IDictionary<TKey, TValue> WithDefaultValue<TValue, TKey>(this IDictionary<TKey, TValue> dictionary, TValue defaultValue ) {
return new DefaultableDictionary<TKey, TValue>(dictionary, defaultValue);
}
}
}
This project is a simple decorator for an IDictionary object and an extension method to make it easy to use.
The DefaultableDictionary will allow for creating a wrapper around a dictionary that provides a default value when trying to access a key that does not exist or enumerating through all the values in an IDictionary.
Example: var dictionary = new Dictionary<string, int>().WithDefaultValue(5);
Blog post on the usage as well.
No, nothing like that exists. The extension method is the way to go, and your name for it (GetValueOrDefault) is a pretty good choice.

Categories