Beim Entwickeln bin ich bisher auf das Problem gestoßen, dass ich einen Wert innerhalb einer Liste anhand von mehreren zusammengesetzten Schlüsseln identifizieren muss. Eine Hashtable bietet von "Natur" aus aber leider nur einen möglichen Schlüssel. Eine Möglichkeit wäre natürlich sich einen Schlüssel "zusammenzuparsen".
Ein weitere Möglichkeit, und wie ich finde auch die elegantere Methode , ist die Folgende. Ausgangspunkt ist hier eine Hashtable welches als Schlüssel den ersten Teil des zusammengesetzten Schlüssel besitzt. Als Wert ist wiederum eine Hashtable eingefügt, welche den zweiten Teil des Schlüssel zur Identifierung besitzt. Und so geht das Spiel runter bis zum letzten Schlüssel.
namespace MultiKeyHashtable{ /// <summary> /// Ermöglicht das Speichern von Werten mit mehreren zusammengesetzten Schlüsseln /// </summary> public class MultiKeyHashtable { private Hashtable _Root; private int _KeysCount; /// <summary> /// Legt eine neue Instanz an /// </summary> /// <param name="keysCount">Anzahl der Schlüssel, die zusammen eindeutig sein müssen</param> public MultiKeyHashtable(int keysCount) { this._KeysCount = keysCount; if (keysCount > 0) { this._Root = new Hashtable(); } else { throw new FormatException("Die Schlüsselanzahl der MultiKeyHashtable muss größer null sein. Wert: " + keysCount); } } /// <summary> /// Ermöglicht das Einfügen bzw. das Auslesen von Schlüssel- / Wertpaaren /// </summary> public object this [params object[] keys] { get { if (this.CheckKeyCount(keys.Length)) { return this.GetValue(this._Root, 0, keys); } return null; } set { if (this.CheckKeyCount(keys.Length)) { this.SetValue(this._Root, 0, value, keys); } } } /// <summary> /// Fügt für den angegebenen Schlüssel den Wert ein /// </summary> /// <param name="value"></param> /// <param name="keys"></param> public void Add(object value, params object[] keys) { if (this.CheckKeyCount(keys.Length)) { this.SetValue(this._Root, 0, value, keys); } } /// <summary> /// Überprüft ob ein Schlüssel vorhanden ist oder nicht /// </summary> /// <param name="keys"></param> /// <returns></returns> public bool ContainsKey(params object[] keys) { if (this.CheckKeyCount(keys.Length)) { if (this.GetValue(this._Root, 0, keys) != null) { return true; } } return false; } /// <summary> /// Entfernt für den angegebenen Schlüssel den eingetragenen Wert /// </summary> /// <param name="keys">zusammengesetzt eindeutiger Schlüssel</param> public void Remove(params object[] keys) { if (this.CheckKeyCount(keys.Length)) { this.RemoveValue(this._Root, 0, keys); } } private bool CheckKeyCount(int count) { if (count == this._KeysCount) { return true; } else { throw new FormatException("Die Parameteranzahl (" + count + ") stimmt nicht mit der initialen Schüsselanzahl (" + this._KeysCount + ") überein. "); } } private object GetValue(Hashtable currentHt, int counter, params object[] keys) { if (currentHt.ContainsKey(keys.GetValue(counter))) { int c = this._KeysCount; if (counter == c--) { //Wert vorhanden, Ende erreicht, Value zurückgeben return currentHt[keys.GetValue(counter)]; } else { //Wert vorhanden --> weiter in die Tiefe gehen Hashtable nextHt = currentHt[keys.GetValue(counter)] as Hashtable; this.GetValue(nextHt, counter + 1, keys); //sollte nicht eintreffen durch die Rekursion return null; } } else { //Wert wurde nicht gefunden return null; } } private Hashtable SetValue(Hashtable currentHt, int counter, object value, params object[] keys) { if (!currentHt.ContainsKey(keys.GetValue(counter))) { //Wert nicht vorhanden int c = this._KeysCount - 1; if (counter == c) { //Ende erreicht currentHt.Add(keys.GetValue(counter), value); return currentHt; } else { //nächste Hashtable hinzufügen currentHt.Add(keys.GetValue(counter), this.SetValue(new Hashtable(), counter + 1, value, keys)); return currentHt; } } else { //key bereits vorhanden int c = this._KeysCount - 1; if (counter == c) { //Ende erreicht throw new ArgumentException("Der Key ist bereits vorhanden."); } else { Hashtable nextHt = currentHt[keys.GetValue(counter)] as Hashtable; currentHt.Remove(keys.GetValue(counter)); currentHt.Add(keys.GetValue(counter), SetValue(nextHt, counter + 1, value, keys)); } } //SetValue ist abgearbeitet return null; } private void RemoveValue(Hashtable currentHt, int counter, params object[] keys) { if (currentHt.ContainsKey(keys.GetValue(counter))) { int c = this._KeysCount; if (counter == c--) { //Wert vorhanden, Ende erreicht, löschen currentHt.Remove(keys.GetValue(counter)); } else { //vorhanden und löschen Hashtable nextHt = currentHt[keys.GetValue(counter)] as Hashtable; this.RemoveValue(nextHt, counter + 1, keys); } } } }}
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.