The normal dictiory separates the key from the value... but what if the key is a part of the item it stores? It then forces you to enter the same things twice, once for the key and agian for the item. I never liked it so I thought I write really simple class that takes this unecessary step away a makes life easier again by allowing you to specify a key selector like the ToDictionary
extension does.
public class AutoDictionary<TKey, TItem> : ICollection<TItem>, IEnumerable<TItem>
{
private readonly Func<TItem, TKey> _keySelector;
private readonly IDictionary<TKey, TItem> _items;
public AutoDictionary(Func<TItem, TKey> keySelector)
{
_keySelector = keySelector;
_items = new Dictionary<TKey, TItem>();
}
public AutoDictionary(Func<TItem, TKey> keySelector, IEqualityComparer<TKey> equalityComparer)
: this(keySelector)
{
_items = new Dictionary<TKey, TItem>(equalityComparer);
}
public AutoDictionary(Func<TItem, TKey> keySelector, IDictionary<TKey, TItem> other)
: this(keySelector)
{
_keySelector = keySelector;
_items = new Dictionary<TKey, TItem>(other);
}
public TItem this[TKey key]
{
get { return _items[key]; }
set { _items[key] = value; }
}
public int Count => _items.Count;
public bool IsReadOnly => false;
public void Add(TItem item) => _items.Add(_keySelector(item), item);
public void Clear() => _items.Clear();
public bool TryGetItem(TKey key, out TItem item) => _items.TryGetValue(key, out item);
public bool Contains(TItem item) => _items.ContainsKey(_keySelector(item));
public void CopyTo(TItem[] array, int arrayIndex) { }
public bool Remove(TItem item) => _items.Remove(_keySelector(item));
public IEnumerator<TItem> GetEnumerator() => _items.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
I wanted to make all methods use lambdas but the constructor doesn't allow this :-(
Usage:
class Foo
{
public string Name { get; set; }
public int Bar { get; set;}
public double Baz { get; set;}
}
var autoDic = new AutoDictionary<string, Foo>(x => x.Name)
{
new Foo { Name = "foo1", Bar = 1 },
new Foo { Name = "foo2", Bar = 2 },
//new Foo { Name = "foo1", Bar = 1 }, // bam!
};
var foo1 = autoDic["foo1"];
I guess I've reinvented the wheel, haven't I? ;-)