Building on this question, is there a simple solution for having a multi-key dictionary where either key individually can be used to identify the value?
ie.
MultikeyDictionary<TKey1, TKey2, TValue> foo;
foo.Add(key1, key2, value);
myValue = foo[key1];
// value == myValue
foo.Remove(key2);
myValue = foo[key1]; // invalid, Exception or null returned
This blog post seems to detail a rather decent implementation.
Multi-key generic dictionary class for C#
MultiKeyDictionary is a C# class
that wraps and extends the Generic
Dictionary object provided by
Microsoft in .NET 2.0 and above. This
allows a developer to create a generic
dictionary of values and reference the
value list through two keys instead of
just the one provided by the Microsoft
implementation of the Generic
Dictionary<...>. You can see my
article on CodeProject (here), however
this code is more up-to-date and bug
free.
Yes, define a class that adds the object to an internal hashtable with both keys,
public MyClass<k1, k2, T>: Dictionary<object, T>
{
private Dictionary<k1, k2> keyMap;
public new Add(k1 key1Val, k2 key2Val, T object)
{
keyMap.Add(key1Val, key2Val);
base.Add(k2, object)
}
public Remove(k1 key1Val)
{
base.Remove(keyMap[key1Val]);
keyMap.Remove(key1Val);
}
public Remove(k2 key2Val)
{
base.Remove(key2Val);
keyMap.Remove(key2Val);
}
}
There's nothing built into .NET BCL for this type of collection at the moment.
I see two options:
Use a two-level dictionary. The first level maps different keys to some common unique key (let's say a GUID), and the second level maps the GUID to the actual value.
Create a custom key class and implement Equals() and GetHashCode() so that any one component of the key is sufficient to find the entire key. You could then supply helper methods to construct instances of the key using only one of the values so that you could do lookups.
Another simple (and effective) implementation would be to use PowerCollections' Pair<TFirst, TSecond> type as a dictionary key, something like
Dictionary<Pair<TKey1, TKey2>, TValue> foo;
foo.Add(new Pair<TKey1, TKey2>(key1, key2), value);
Pair<> implements Equals and GetHashCode consistently, so you don't need to resort to multi-level dictionaries (which are more cumbersome and probably less effective).
There's also a Triple<TFirst, TSecond, TThird> if you need a 3-key dictionary.
I find many answers here unnecessarily complex, less performant or plain unusable. The best approach would be to have a KeyValuePair<> of the secondary key and the value clubbed together as the Value of either dictionaries. This lets you have just one lookup for for removal and updation operations. A straightforward implementation:
public class DualDictionary<TKey1, TKey2, TValue> : IEnumerable<KeyValuePair<Tuple<TKey1, TKey2>, TValue>>
{
Dictionary<TKey1, KeyValuePair<TKey2, TValue>> _firstKeys;
Dictionary<TKey2, KeyValuePair<TKey1, TValue>> _secondKeys;
public int Count
{
get
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Count;
}
}
public ICollection<TKey1> Key1s
{
get { return _firstKeys.Keys; }
}
public ICollection<TKey2> Key2s
{
get { return _secondKeys.Keys; }
}
public IEnumerable<TValue> Values
{
get { return this.Select(kvp => kvp.Value); }
}
public DualDictionary(IEqualityComparer<TKey1> comparer1 = null, IEqualityComparer<TKey2> comparer2 = null)
{
_firstKeys = new Dictionary<TKey1, KeyValuePair<TKey2, TValue>>(comparer1);
_secondKeys = new Dictionary<TKey2, KeyValuePair<TKey1, TValue>>(comparer2);
}
public bool ContainsKey1(TKey1 key)
{
return ContainsKey(key, _firstKeys);
}
private static bool ContainsKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.ContainsKey(key);
}
public bool ContainsKey2(TKey2 key)
{
return ContainsKey(key, _secondKeys);
}
public TValue GetValueByKey1(TKey1 key)
{
return GetValueByKey(key, _firstKeys);
}
private static TValue GetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict[key].Value;
}
public TValue GetValueByKey2(TKey2 key)
{
return GetValueByKey(key, _secondKeys);
}
public bool TryGetValueByKey1(TKey1 key, out TValue value)
{
return TryGetValueByKey(key, _firstKeys, out value);
}
private static bool TryGetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, out TValue value)
{
KeyValuePair<T, TValue> otherPairing;
bool b = TryGetValue(key, dict, out otherPairing);
value = otherPairing.Value;
return b;
}
private static bool TryGetValue<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict,
out KeyValuePair<T, TValue> otherPairing)
{
return dict.TryGetValue(key, out otherPairing);
}
public bool TryGetValueByKey2(TKey2 key, out TValue value)
{
return TryGetValueByKey(key, _secondKeys, out value);
}
public bool Add(TKey1 key1, TKey2 key2, TValue value)
{
if (ContainsKey1(key1) || ContainsKey2(key2)) // very important
return false;
AddOrUpdate(key1, key2, value);
return true;
}
// dont make this public; a dangerous method used cautiously in this class
private void AddOrUpdate(TKey1 key1, TKey2 key2, TValue value)
{
_firstKeys[key1] = new KeyValuePair<TKey2, TValue>(key2, value);
_secondKeys[key2] = new KeyValuePair<TKey1, TValue>(key1, value);
}
public bool UpdateKey1(TKey1 oldKey, TKey1 newKey)
{
return UpdateKey(oldKey, _firstKeys, newKey, (key1, key2, value) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateKey<S, T>(S oldKey, Dictionary<S, KeyValuePair<T, TValue>> dict, S newKey,
Action<S, T, TValue> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(oldKey, dict, out otherPairing) || ContainsKey(newKey, dict))
return false;
Remove(oldKey, dict);
updater(newKey, otherPairing.Key, otherPairing.Value);
return true;
}
public bool UpdateKey2(TKey2 oldKey, TKey2 newKey)
{
return UpdateKey(oldKey, _secondKeys, newKey, (key1, key2, value) => AddOrUpdate(key2, key1, value));
}
public bool UpdateByKey1(TKey1 key, TValue value)
{
return UpdateByKey(key, _firstKeys, (key1, key2) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, Action<S, T> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, dict, out otherPairing))
return false;
updater(key, otherPairing.Key);
return true;
}
public bool UpdateByKey2(TKey2 key, TValue value)
{
return UpdateByKey(key, _secondKeys, (key1, key2) => AddOrUpdate(key2, key1, value));
}
public bool RemoveByKey1(TKey1 key)
{
return RemoveByKey(key, _firstKeys, _secondKeys);
}
private static bool RemoveByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> keyDict,
Dictionary<T, KeyValuePair<S, TValue>> valueDict)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, keyDict, out otherPairing))
return false;
if (!Remove(key, keyDict) || !Remove(otherPairing.Key, valueDict))
throw new Exception("somewhere logic went wrong and your data got corrupt");
return true;
}
private static bool Remove<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.Remove(key);
}
public bool RemoveByKey2(TKey2 key)
{
return RemoveByKey(key, _secondKeys, _firstKeys);
}
public void Clear()
{
_firstKeys.Clear();
_secondKeys.Clear();
}
public IEnumerator<KeyValuePair<Tuple<TKey1, TKey2>, TValue>> GetEnumerator()
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Select(kvp => new KeyValuePair<Tuple<TKey1, TKey2>, TValue>(Tuple.Create(kvp.Key, kvp.Value.Key),
kvp.Value.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Few things to note:
I have implemented only IEnumerable<>. I don't think ICollection<> makes sense here since the method names all could be way different for this special collection structure. Up to you to decide what should go inside IEnumerable<>.
I have attempted for some weird exceptions to be thrown here and there - just for data integrity. Just to be on the safer side so that you know if ever my code has bugs.
I have named methods in such a way that its compilable even when Key1 and Key2 are of the same type.
Performance: You can lookup for Value with either of the Keys. Get and Contains method require just 1 lookup (O(1)). Add requires 2 lookups and 2 adds. Update requires 1 lookup and 2 adds. Remove takes 3 lookups.
I tried this and it works perfectly (include add, remove & indexer)
public class MultikeyDictionary<K1, K2, V> : Dictionary<KeyValuePair<K1, K2>, V>
{
public V this[K1 index1, K2 index2]
{
get
{
return this[new KeyValuePair<K1, K2>(index1, index2)];
}
set
{
this[new KeyValuePair<K1, K2>(index1, index2)] = value;
}
}
public bool Remove(K1 index1, K2 index2)
{
return base.Remove(new KeyValuePair<K1,K2>(index1, index2));
}
public void Add(K1 index1, K2 index2, V value)
{
base.Add(new KeyValuePair<K1, K2>(index1, index2), value);
}
}
and even I extended it to 4 values:
public class MultikeyDictionary<K1, K2, K3, V> : MultikeyDictionary<KeyValuePair<K1, K2>, K3, V>
{
public V this[K1 index1, K2 index2, K3 index3]
{
get
{
return base[new KeyValuePair<K1, K2>(index1, index2), index3];
}
set
{
base[new KeyValuePair<K1, K2>(index1, index2), index3] = value;
}
}
public bool Remove(K1 index1, K2 index2, K3 index3)
{
return base.Remove(new KeyValuePair<K1, K2>(index1, index2), index3);
}
public void Add(K1 index1, K2 index2, K3 index3, V value)
{
base.Add(new KeyValuePair<K1, K2>(index1, index2), index3, value);
}
}
Enjoy,
Ofir
Sure, it's an OO language and you can implement whatever O's you want. You are going to have some ambiguity to resolve (what if TKey1 and TKey2 are the same type, which methods get called then?)
You won't be able to define the overloads for both types, and the generics system doesn't allow for an arbitrary number of types (like methods allow params). So, you'd be stuck with a set of classes which defined 2, 3, 4, etc. simultaneous keys. Additionally, you'd have to use object as the parameter for get and set, using runtime type checks to simulate the overload.
Additionally, you'd only store one dictionary of <TKEY1,VAL>, the other dictionaries would be of <TKEY2,TKEY1>, <TKEY3,TKEY1> and would act as indexes on the main dictionary.
It's mostly boiler plate code.
You may find my IndexMap implementation to be a good base for rewriting it from Java into C#. The programming model isn't as elegant as I'd prefer, but it isn't meant for developing with directly. Rather it lies behind a caching library which supplies standard annotations to allow for a succinct coding style. By using the Map interface it provides a clean compositional model when combining it with self-populating, expirational, and evictible map decorators. I am sure that someone could come up with a nice programming interface for direct usage where it is acceptable to lose the benefit of the Map interface.
Not a direct solution and not viable for multi keys, but worked for my use case.
Dictionary<Guid, Object> objs = new Dictionary<Guid, Object>();
Dictionary<int, Guid> guids = new Dictionary<int, Guid>();
private void Set(object sender, Object obj)
{
objs[obj.Guid] = obj;
guids[obj.Id] = obj.Guid;
}
public Object Get(int id)
{
return guids.ContainsKey(id) ? Get(guids[id]) : null;
}
public Object Get(Guid guid)
{
return objs.ContainsKey(guid) ? objs[guid] : null;
}
I wrote a MultiKeyDictionary package for net472, net481, netstandard2.1, and net6.0.
In this version, however, you can combine key1 with arbitrary key2s. You can slice, contains, add, remove, clear, set, index, trygetvalue, tryslice, and enumerate. There's a maximum of 5 keys supported.
Related
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.
I have
Dictionary<string, List<int>> myDict = new Dictionary<string, List<int>>();
and at some points I want to add numbers to myDict for a specific Dictionary key.
I am currently doing
if (!myDict.ContainsKey(newKey)){
myDict[newKey] = new List<int>();
}
myDict[newKey].Add(myNumber);
but that seems to be error prone to forgetting the ContainsKey check at some point.
I have searched for a way to make Dictionaries return a new List in case myDict["entry"] doesn't exist yet, but I couldn't find anything.
Here's a relatively simple implementation of the LazyLookup example I mentioned. It only implements IEnumerable out of brevity/simplicity to answer the question.
Essentially, upon accessing an index, it will make sure it has already been initialized to a new instance of the List<T> class.
public class LazyLookup<TKey, TValue> : IEnumerable<List<TValue>>
{
private readonly Dictionary<TKey, List<TValue>> CachedEntries;
private readonly Func<List<TValue>> LazyListCreator;
public LazyLookup()
: this(() => new List<TValue>())
{
}
public LazyLookup(Func<List<TValue>> lazyListCreator)
{
this.LazyListCreator = lazyListCreator;
this.CachedEntries = new Dictionary<TKey, List<TValue>>();
}
public List<TValue> this[TKey key]
{
get
{
return GetOrCreateValue(key);
}
}
private List<TValue> GetOrCreateValue(TKey key)
{
List<TValue> returnValue;
if (!CachedEntries.TryGetValue(key, out returnValue))
{
returnValue = LazyListCreator();
CachedEntries[key] = returnValue;
}
return returnValue;
}
public IEnumerator<List<TValue>> GetEnumerator()
{
return CachedEntries.Values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
With some usage:
var lazyLookup = new LazyLookup<string, int>();
lazyLookup["nocheck"].Add(9001);
//outputs 9001
Console.WriteLine(lazyLookup["nocheck"][0]);
//outputs 0 as it's a newly initialized list
Console.WriteLine(lazyLookup["someOtherLookup"].Count);
At this point, you could update it to be threadsafe (as GetOrCreateValue currently is not threadsafe), or generalize it so it doesn't assume it's of List<T> but any type, or extend it to implement the full IDictionary<TKey, TValue> interface. But at minimum, if the above pattern you posted is used often, you may consider swapping direct usage of the dictionaries with some encapsulation which trivializes the task for you and eliminates code duplication.
You can use TryGetValue:
List<int> list;
if(!myDict.TryGetValue(newKey, out list))
{
list = new List<int>();
myDict.Add(newKey, list);
}
list.Add(myNumber);
If the Dictionary is a field i would encapsulate the acces in a method:
Dictionary<string, List<int>> myDict = new Dictionary<string, List<int>>();
public void AddNumber(string key, int value)
{
List<int> list;
if(!myDict.TryGetValue(key, out list))
{
list = new List<int>();
myDict.Add(key, list);
}
list.Add(value);
}
If you use ConcurrentDictionary<T>, you can do this:
myDict.GetOrAdd(newKey, new List<int>()).Add(myNumber);
You can actually use the others' suggestions. By encapsulating the access in a method or even using ConcurrentDictionary.
But for me, I would have a custom dictionary so you can actually implement what myDict["entry"] does if it did not see an element.
Good thing with this is you have full control on how you would like this dictionary to behave.
class MyCustomDictionary<TKey, TValue> : IDictionary<TKey, TValue>
where TValue : class, new()
{
private Dictionary<TKey, TValue> _dictionary;
public MyCustomDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
public TValue this[TKey key] // this is what's important
{
get
{
TValue val;
if (!_dictionary.TryGetValue(key, out val)) // if there is no element for that key, add a new element and return it
{
_dictionary.Add(key, new TValue());
return _dictionary[key];
}
else // else return the found element
{
return val;
}
}
set
{
_dictionary[key] = value;
}
}
public void Add(TKey key, TValue value)
{
_dictionary.Add(key, value);
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return _dictionary.Keys; }
}
public bool Remove(TKey key)
{
return _dictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return _dictionary.Values; }
}
public void Add(KeyValuePair<TKey, TValue> item)
{
_dictionary.Add(item.Key, item.Value);
}
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.ToList().CopyTo(array, arrayIndex); // do you need this? you can leave this :)
}
public int Count
{
get { return _dictionary.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return _dictionary.Remove(item.Key);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
}
Then you use it like:
MyCustomDictionary<string, List<int>> myCustomDict = new MyCustomDictionary<int, List<int>>();
// return a new List of int
var someElementThatIsNotFound = myCustomDict["keyThatIsNonExistent"];
You can use TryGetValue method: if there's the key in the dictionary
you should just add the value into the list; otherwise you should
add a list with a value:
List<int> list
if (myDict.TryGetValue(newKey, out list))
list.Add(myNumber);
else
myDict.Add(newKey, new List<int>() { myNumber });
Lots of good answers already. I implemented an extension method for this exact reason:
public static TVALUE GetOrSet<TKEY, TVALUE>(this IDictionary<TKEY, TVALUE> self,
TKEY key,
Func<TVALUE> defaultValue)
{
TVALUE value;
if (!self.TryGetValue(key, out value))
{
value = defaultValue();
self[key] = value;
}
return value;
} // eo GetOrSet
Note that it takes a function to assign the value if it is not present. Either way, the value will be returned. Usage:
var dict = new Dictionary<string, List<int>>();
List<int> ints = dict.GetOrSet("list1", () => return new List<int>());
ints.Add(1);
If you're not referencing it again, you could potentially be less verbose:
dict.GetOrSet("list1", () => return new List<int>()).Add(1);
Essentially, I want a data structure that resembles Dictionary, but having a difference that its values are also unique. In another words, it depicts a one to one relationship rather than one to many.
An example should explain better. Suppose I call this new data structure MyMapping, and I want to save names of married couples in it:
MyMapping<string, string> myMapping = new MyMapping<string, string>();
myMapping.Add("Joe", "Ann");
myMapping.Add("Ann", "Joe");// not allowed
myMapping.Add("Joe", "Mary");// not allowed
myMapping.Add("William", "Katie");// ok
string partner = myMapping["Ann"];// result is Joe
partner = myMapping["Joe"];//result is Ann
what you're looking for is also called a Two-way dictionary. Take a look at other SO answers to the same question.
I started building a TwoWayDictionary for you based on IDictionary
http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx
//only one generic parameter needed, as key and value have same type.
public class TwoWayDictionary<TKey> : IDictionary<TKey, TKey>
{
private Dictionary<TKey, TKey> _primary;
private Dictionary<TKey, TKey> _secondary;
public TwoWayDictionary()
{
_primary = new Dictionary<TKey, TKey>();
_secondary = new Dictionary<TKey, TKey>();
}
public int Count {get{return _primary.Count;}}
public bool IsReadOnly {get{return _primary.IsReadOnly;}}
public TKey this[TKey key]
{
get
{
return this.GetValue(key);
}
set
{
this.Add(key, value);
}
}
public ICollection<TKey> Keys {get {return _primary.Keys;}}
public ICollection<TKey> Values {get {return _primary.Values;}}
private TKey GetValue(TKey key)
{
if (_primary.ContainsKey(key))
{
return _primary[key];
}
if (_secondary.ContainsKey(key))
{
return _secondary[key];
}
throw new KeyNotFoundException("key is not found");
}
public void Add(KeyValuePair<TKey, TKey> item)
{
this.Add(item.Key, item.Value);
}
public void Add(TKey key, TKey value)
{
if (key == null || value == null)
{
throw new ArguementNullException("key or value is null");
}
if (_primary.ContainsKey(key) || _secondary.ContainsKey(key)
|| _primary.ContainsKey(value) || _secondary.ContainsKey(value))
{
throw new ArgumentException("Item with same key or value already exists");
}
_primary.Add(key, value);
_secondary.Add(value, key);
}
public void Clear()
{
_primary.Clear();
_secondary.Clear();
}
public void Contains(KeyValuePair<TKey, TKey> item)
{
return _primary.Contains(item) || _secondary.Contains(item);
}
public void ContainsKey(TKey key)
{
return _primary.ContainsKey(key) || _secondary.ContainsKey(key);
}
public void CopyTo(KeyValuePair<TKey, TKey>[] array, int arrayIndex)
{
return _primary.CopyTo(array, arrayIndex);
}
... TODO finish implementing IDictionary
Two dictionaries are not necessary - a dictionary with a HashSet will suffice. The HashSet will of course hold and guard the values.
EDIT: additional explanation regarding question in the comment
The new collection would consist of an instance of a Dictionary and a HashSet, like this:
class UniqueValueDictionary<TKey, TValue>
{
//...
private Dictionary<TKey, TValue> dictionary;
private HashSet<TValue> valueSet;
}
When inserting to the dictionary you verify if the value already exists:
public void Add(TKey key, TValue value)
{
if (valueSet.Contains(value))
{
//throw appropriate exception
}
dictionary.Add(key, value);
valueSet.Add(value);
}
When removing:
public void Remove(TKey key)
{
//check if key exists, throw exception if not
var value = dictionary[key];
dictionary.Remove(key);
valueSet.Remove(value);
}
I'm not sure if I'm doing something wrong here or if it needs to be fixed...
I have a custom Dictionary wrapper class and here is a snippet of the code that is necessary.
public int Count
{
get
{
Contract.Ensures(Contract.Result<int>() >= 0);
return InternalDictionary.Count;
}
}
public bool ContainsKey(TKey key)
{
//This contract was suggested by the warning message, if I remove it
//I still get the same warning...
Contract.Ensures(!Contract.Result<bool>() || Count > 0);
return InternalDictionary.ContainsKey(key);
}
The only reason I added the line for the ContainsKey is because I got the following warning message (and still do): Codecontracts: ensures unproven: !Contract.Result<bool>() || #this.Count > 0. I can remove this line and still get the SAME ISSUE!
What do I do here to get rid of these issues?
Update:
I also tried (as suggested)...
public Boolean ContainsKey(TKey key)
{
Contract.Requires(Count == 0 || InternalDictionary.ContainsKey(key));
Contract.Ensures(!Contract.Result<bool>() || Count > 0);
return InternalDictionary.ContainsKey(key);
}
Warning 5 Method
'My.Collections.Generic.ReadOnlyDictionary2.ContainsKey(type
parameter.TKey)' implements interface method
'System.Collections.Generic.IDictionary2.ContainsKey(type parameter.TKey)', thus cannot add
Requires.
"I have a custom Dictionary wrapper class" - that implements IDictionary<TKey, TValue>. Interface methods can specify contracts, and the class methods that implement them must meet the contracts. In this case, IDictionary<TKey, TValue>.ContainsKey(TKey) has the contract you're asking about:
Contract.Ensures(!Contract.Result<bool>() || this.Count > 0);
Logically, !a || b can be read as a ===> b (a implies b), and using that, we can translate this to English:
If ContainsKey() returns true, the dictionary must not be empty.
This is a perfectly sensible requirement. An empty dictionary must not claim to contain keys. This is what you need to prove.
Here's a sample DictionaryWrapper class that adds Contract.Ensures to promise that the implementation detail of Count being equal to innerDictionary.Count is a hard guarantee that other methods can rely upon. It adds a similar Contract.Ensures to ContainsKey so that the IDictionary<TKey, TValue>.TryGetValue contract is also verifiable.
public class DictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
{
IDictionary<TKey, TValue> innerDictionary;
public DictionaryWrapper(IDictionary<TKey, TValue> innerDictionary)
{
Contract.Requires<ArgumentNullException>(innerDictionary != null);
this.innerDictionary = innerDictionary;
}
[ContractInvariantMethod]
private void Invariant()
{
Contract.Invariant(innerDictionary != null);
}
public void Add(TKey key, TValue value)
{
innerDictionary.Add(key, value);
}
public bool ContainsKey(TKey key)
{
Contract.Ensures(Contract.Result<bool>() == innerDictionary.ContainsKey(key));
return innerDictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get
{
return innerDictionary.Keys;
}
}
public bool Remove(TKey key)
{
return innerDictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return innerDictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get
{
return innerDictionary.Values;
}
}
public TValue this[TKey key]
{
get
{
return innerDictionary[key];
}
set
{
innerDictionary[key] = value;
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
innerDictionary.Add(item);
}
public void Clear()
{
innerDictionary.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return innerDictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
innerDictionary.CopyTo(array, arrayIndex);
}
public int Count
{
get
{
Contract.Ensures(Contract.Result<int>() == innerDictionary.Count);
return innerDictionary.Count;
}
}
public bool IsReadOnly
{
get
{
return innerDictionary.IsReadOnly;
}
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return innerDictionary.Remove(item);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return innerDictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return innerDictionary.GetEnumerator();
}
}
Frankly I don't understand the point of the contract. The contract is
Contract.Ensures(!Contract.Result<bool>() || Count > 0);
What are you trying to say? You can neither guarantee that the dictionary contains the key, nor that the dictionary contains any values at all. So this contract can't always be met. That's what the verifier is telling you: it can't prove that this statement you are promising to be true is true.
The best you can ensure that the return value is true or the return value is false and that Count is greater than zero or equal to zero But what's the point of such a contract? The caller already knows this.
Given that, I wouldn't bother with a contract here at all.
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.