You can implement your own KeyedCollection trivially if the extra overhead that comes with the factory settings is not worth it. The original KeyedCollection in System.Collections.ObjectModel is an internal a Dictionary<TKey, TItem> and a List<TItem> , which means that you can have operations defined on both IList<> and IDictionary<> . For example, you can insert, access by index, move the collection in the inserted order (all that IList<> makes it easy), and at the same time, you can quickly search based on a key (using a dictionary). This means that when you add or delete an item, they must be executed in both basic sets, in addition to small memory overhead, to store additional List<> (but objects are not duplicated as such). Although the speed of adding is not very dependent ( List<> adding O (1)), the speed of removal is slightly reduced.
If you do not need insertion order and index access:
public class KeyedCollection<TKey, TItem> : ICollection<TItem> { MemberInfo _keyInfo; Func<TItem, TKey> _keySelector; Dictionary<TKey, TItem> _dict; public TItem this[TKey key] { get { return _dict[key]; } } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return false; } } public ICollection<TKey> Keys { get { return _dict.Keys; } } private ICollection<TItem> Items { get { return _dict.Values; } } public KeyedCollection(Expression<Func<TItem, TKey>> keySelector, IEqualityComparer<TKey> comparer = null) { var keyExpression = keySelector.Body as MemberExpression; if (keyExpression != null) _keyInfo = keyExpression.Member; _keySelector = keySelector.Compile(); _dict = new Dictionary<TKey, TItem>(comparer); } private TKey GetKeyForItem(TItem item) { return _keySelector(item); } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public bool Contains(TItem item) { return ContainsKey(GetKeyForItem(item)); } public bool TryGetItem(TKey key, out TItem item) { return _dict.TryGetValue(key, out item); } public void Add(TItem item) { _dict.Add(GetKeyForItem(item), item); } public void AddOrUpdate(TItem item) { _dict[GetKeyForItem(item)] = item; } public bool UpdateKey(TKey oldKey, TKey newKey) { TItem oldItem; if (_keyInfo == null || !TryGetItem(oldKey, out oldItem) || !SetItem(oldItem, newKey))
I implemented ICollection<TItem> to make it more standard, and also get the initializer syntax of a good collection! :)
Using an example:
var p1 = new Person { Name = "a" }; var p2 = new Person { Name = "b" }; var people = new KeyedCollection<string, Person>(p => p.Name) { p1, p2 };
nawfal
source share