Is there a dictionary like a collection that can use the property of its value as a key?

Instead of using Dictionary<TKey,TValue> I need some type of collection class that can use the value property as a key, is there something like this?

+6
collections dictionary
source share
3 answers

Yes there is - System.Collections.ObjectModel.KeyedCollection<TKey, TValue> .

This essay, and I do not see specific derived classes in the structure, but all you need to implement is GetKeyForItem , as far as I can see. For example, you can do this with a delegate:

 public class DelegatingKeyedCollection<TKey, TItem> : System.Collections.ObjectModel.KeyedCollection<TKey, TItem> { private readonly Func<TItem, TKey> keySelector; public DelegatingKeyedCollection(Func<TItem, TKey> keySelector) { this.keySelector = keySelector; } protected override TKey GetKeyForItem(TItem item) { return keySelector(item); } } 
+9
source share

KeyedCollection, as John Skeet says, is an obvious candidate.

A few random notes about this class:

  • You, of course, want the property that you used as the key to be read-only.

  • Its Contains(TItem item) method inherits from Collection<T> and is implemented by iterating through the collection. This can be much slower than Contains(TKey key) . It’s too easy for developers to make a mistake with the wrong overload, so you should consider implementing your own method Contains(TItem item) :

     public new bool Contains(TItem item) { if (item == null) throw new ArgumentNullException("item"); return this.Contains(GetKeyForItem(item)); } 
  • Unlike IDictionary, it does not have a TryGetValue method. This may be useful, and it may be worth implementing your own:

     public bool TryGetValue(TKey key, out TItem item) { // If the dictionary exists, use it if (Dictionary != null) return Dictionary.TryGetValue(key, out item); // Else do it the hard way if (!this.Contains(key)) { item = default(TItem); return false; } item = this[key]; return true; } 
  • It does not support key enumeration, which may be useful:

     public IEnumerable<TKey> GetKeys() { foreach (TItem item in this) { yield return GetKeyForItem(item); } } 
  • Serialization can be inefficient because it will serialize both the internal list and the internal dictionary. You can get around this if you need using custom serialization.

+4
source share

Use normal, and when you set a pair of key values, specify the property of the value you are interested in.

It was too easy, I must not understand your request.

You might want to use an arbitrary property later, rather than during input. In this case, I think you will have to use several dictionary objects (possibly related in the helper class).

+2
source share

All Articles