Making a SortedList readonly - c#

I often have classes exposing lists as ReadOnlyCollection<T>s, i.e.
public class Class
{
List<string> list;
public ReadOnlyCollection<string> TheList
{
get { return list.AsReadOnly(); }
}
}
What's the best way to do this for an IDictionary<T,U> such as a SortedList<string, string>?

public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> sourceDictionary;
public ICollection<TKey> Keys
{
get { return sourceDictionary.Keys; }
}
public ICollection<TValue> Values
{
get { return sourceDictionary.Values; }
}
public TValue this[TKey key]
{
get { return sourceDictionary[key]; }
set { throw new NotSupportedException(); }
}
public int Count
{
get { return sourceDictionary.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public ReadOnlyDictionary(IDictionary<TKey, TValue> sourceDictionary)
{
AssertUtilities.ArgumentNotNull(sourceDictionary, "sourceDictionary");
this.sourceDictionary = sourceDictionary;
}
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw new NotSupportedException();
}
public bool ContainsKey(TKey key)
{
return sourceDictionary.ContainsKey(key);
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw new NotSupportedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
return sourceDictionary.TryGetValue(key, out value);
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw new NotSupportedException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return sourceDictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
sourceDictionary.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return sourceDictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)sourceDictionary).GetEnumerator();
}
}
[Edit]
#Simon Buchan and #Cory Nelson pointed out that it is better to use implicit interface implementation for those methods that are not supported. Updated the code accordingly.

Create a ReadOnlyDictionary class that implements IDictionary as a wrapper around an internal Dictionary instance. For the methods that would modify the dictionary, throw an exception. Implement IsReadOnly to return true. Implement all other methods to pass through to the internal Dictionary instance.

You can do it with standard LINQ methods.
Create you source list:
List<String> myList = new List<String>() { "A", "B", "C" };
Project your list into a dictionary using .ToDictionary linq extension method:
var myDictionary = myList.ToDictionary(listItem => listItem);
Note: The lambda expression peeks a key from you list (rembember that dictionary can only contain unique keys; otherwise consider the use of ILookup which represents a dictionary of list).
Reform your dictionary to a SortedDictionary instance:
var mySortedDictionary = new SortedDictionary<string, string>(myDictionary);
Expose your sorted dictionary as an IReadOnlyDictionary interface as follows:
public IReadOnlyDictionary MemberDictionary { get; private set; );
// ...somewhere in your constructor or class's initialization method...
this.MemberDictionary = mySortedDictionary;

Related

How do I inherit from Dictionary<TKey, TValue> but validate the Add method?

How do I ensure that in a Dictionary Generic,
Value Attribute always equals Key * 2?
I wrote a Inheritance class from dictionary with method AddItem.
Now, I want to hide the original base class? How would this be done?
Or is there anyway or option to ensure Data Integrity? This is a simple example, will utilize more complicated examples at work
public class MultipleBy2Test:Dictionary<int, int>
{
public void AddItem(int OriginalAmount int DoubleAmount)
{
base.Add(OriginalAmount, OriginalAmount * 2);
}
}
The Add method isn't virtual, so you can't override it. The only choice that leaves is to encapsulate the dictionary.
public class MultipleBy2Test
{
private readonly Dictionary<int, int> _values = new Dictionary<int, int>();
public void AddItem(int originalAmount)
{
_values.Add(originalAmount, originalAmount * 2);
}
}
Now the class doesn't inherit from Dictionary<int, int> and nothing in its public interface allows access to the dictionary. Data integrity is ensured because nothing but your method can add anything to the dictionary.
Ideally you would just add a few methods to retrieve values and be done, if that were an option.
If you want all of the other methods of a dictionary then you would implement IDictionary<int, int>. Because of what a nuisance this is, I'd start with a generic implementation and make the Add methods virtual. That way if you want another dictionary with different logic you don't have to create another class and implement all this stuff again.
public class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _innerDictionary
= new Dictionary<TKey, TValue>();
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _innerDictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual 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 bool Remove(KeyValuePair<TKey, TValue> item)
{
return _innerDictionary.Remove(item);
}
public int Count => _innerDictionary.Count;
public bool IsReadOnly => _innerDictionary.IsReadOnly;
public bool ContainsKey(TKey key)
{
return _innerDictionary.ContainsKey(key);
}
public virtual void Add(TKey key, TValue value)
{
_innerDictionary.Add(key, value);
}
public bool Remove(TKey key)
{
return _innerDictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _innerDictionary.TryGetValue(key, out value);
}
public virtual TValue this[TKey key]
{
get => _innerDictionary[key];
set => _innerDictionary[key] = value;
}
public ICollection<TKey> Keys => _innerDictionary.Keys;
public ICollection<TValue> Values => _innerDictionary.Values;
}
That gets you a dictionary implementation where you can override the Add methods. You can reject values that doesn't meet your requirements. You could create other overloads for Add if you want to.
public class InheritedDictionaryWithValidation : MyDictionary<int, int>
{
public override void Add(KeyValuePair<int, int> item)
{
Add(item.Key, item.Value);
}
public override void Add(int key, int value)
{
ValidateEntry(key, value);
base.Add(key, value);
}
public override int this[int key]
{
get => base[key];
set
{
ValidateEntry(key, value);
base[key] = value;
}
}
private void ValidateEntry(int key, int value)
{
if (value != key * 2)
throw new ArgumentException("You've violated some rule.");
}
}
You could even go a step further to avoid duplication and introduce an intermediate abstract version for validation:
public abstract class ValidatedDictionary<TKey, TValue> : MyDictionary<TKey, TValue>
{
public override void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public override void Add(TKey key, TValue value)
{
ValidateEntry(key, value);
base.Add(key, value);
}
public override TValue this[TKey key]
{
get => base[key];
set
{
ValidateEntry(key, value);
base[key] = value;
}
}
private void ValidateEntry(TKey key, TValue value)
{
if (!IsEntryValid(key, value))
throw new ArgumentException("The entry is not valid.");
}
protected abstract bool IsEntryValid(TKey key, TValue value);
}
Now you can create dictionaries that validate entries without duplicating anything:
public class MyIntDictionaryWithValidation : ValidatedDictionary<int, int>
{
protected override bool IsEntryValid(int key, int value)
{
return value == key * 2;
}
}

Add Element to Dictionary of Lists

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);

How can I implement a dictionary whose value is also a key?

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);
}

Analogue of Python's defaultdict?

Is there a .NET analogue of Python's defaultdict? I find it useful to write short code, eg. counting frequencies:
>>> words = "to be or not to be".split()
>>> print words
['to', 'be', 'or', 'not', 'to', 'be']
>>> from collections import defaultdict
>>> frequencies = defaultdict(int)
>>> for word in words:
... frequencies[word] += 1
...
>>> print frequencies
defaultdict(<type 'int'>, {'not': 1, 'to': 2, 'or': 1, 'be': 2})
So ideally in C# I could write:
var frequencies = new DefaultDictionary<string,int>(() => 0);
foreach(string word in words)
{
frequencies[word] += 1
}
Here's a simple implementation:
public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : new()
{
public new TValue this[TKey key]
{
get
{
TValue val;
if (!TryGetValue(key, out val))
{
val = new TValue();
Add(key, val);
}
return val;
}
set { base[key] = value; }
}
}
And how you would use it:
var dict = new DefaultDictionary<string, int>();
Debug.WriteLine(dict["foo"]); // prints "0"
dict["bar"] = 5;
Debug.WriteLine(dict["bar"]); // prints "5"
Or like this:
var dict = new DefaultDictionary<string, List<int>>();
dict["foo"].Add(1);
dict["foo"].Add(2);
dict["foo"].Add(3);
Something to get you started. I basically just changed the this indexer. Since I don't know the complete functionality of python's defaultdict I cannot improve it further. Your given example will work.
public class DefaultDictionary<TKey, TValue> : IDictionary<TKey,TValue>
{
private readonly Func<TValue> _defaultSelector;
private readonly Dictionary<TKey, TValue> _values = new Dictionary<TKey, TValue>();
public DefaultDictionary()
: this(() => default(TValue))
{
}
public DefaultDictionary(Func<TValue> defaultSelector)
{
_defaultSelector = defaultSelector;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<TKey, TValue> item)
{
((IDictionary<TKey,TValue>)_values).Add(item);
}
public void Clear()
{
_values.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return ((IDictionary<TKey,TValue>)_values).Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
((IDictionary<TKey, TValue>)_values).CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return ((IDictionary<TKey, TValue>)_values).Remove(item);
}
public int Count { get { return _values.Count; } }
public bool IsReadOnly { get { return ((IDictionary<TKey, TValue>) _values).IsReadOnly; } }
public bool ContainsKey(TKey key)
{
return _values.ContainsKey(key);
}
public void Add(TKey key, TValue value)
{
_values.Add(key, value);
}
public bool Remove(TKey key)
{
return _values.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _values.TryGetValue(key, out value);
}
public TValue this[TKey key]
{
get
{
if (!_values.ContainsKey(key))
{
_values.Add(key, _defaultSelector());
}
return _values[key];
}
set
{
if(!_values.ContainsKey(key))
{
_values.Add(key, _defaultSelector());
}
_values[key] = value;
}
}
public ICollection<TKey> Keys { get { return _values.Keys; } }
public ICollection<TValue> Values { get { return _values.Values; } }
public Dictionary<TKey, TValue> ToDictionary()
{
return new Dictionary<TKey, TValue>(_values);
}
}
I don't think there is an equivalent, but given your example you could do this with LINQ:
var words = new List<string>{ "One", "Two", "Three", "One" };
var frequencies = words.GroupBy (w => w).ToDictionary (w => w.Key, w => w.Count());
The ConcurrentDictionary (in System.Collections.Generic) behaves very similar (although designed for concurrent use)
To retrieve the value:
The GetOrAdd method returns the value for a key, and if it doesn't exist, creates one using a value factory.
To set the value:
The AddOrUpdate method updates a value, or sets it if it doesn't exist yet
Advantages:
Thread safe
Full control over the default value and the update step
Disadvantages:
Slightly more verbose syntax

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