/// <summary> /// Attempts to add the <paramref name="value"/> with the keys /// <paramref name="key1"/>, <paramref name="key2"/>. /// </summary> /// <param name="key1">The <typeparamref name="TKey1"/> which /// is the first key of the <paramref name="value"/> /// to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/>.</param> /// <param name="key2">The <typeparamref name="TKey2"/> which /// is the second key of the <paramref name="value"/> /// to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/>.</param> /// <param name="value">The <typeparamref name="TValue"/> to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/></param> public bool TryAdd(TKey1 key1, TKey2 key2, TValue value) { // Declare the locals relative to the different levels. LevelOne levelOne; /* ------------------------------------------------------\ | Check each level individually, if the key set is | | already present, indicate that nothing was done, and | | yield; otherwise note that it was inserted. | \------------------------------------------------------ */ if (((object)(key1)) == null) { throw new ArgumentNullException("key1"); } bool topLevelLock = false; Monitor.Enter(this.dataCopy, ref topLevelLock); if (this.dataCopy.TryGetValue(key1, out levelOne)) { if (topLevelLock) { Monitor.Exit(this.dataCopy); } if (((object)(key2)) == null) { throw new ArgumentNullException("key2"); } bool levelOneLock = false; Monitor.Enter(levelOne, ref levelOneLock); if (levelOne.ContainsKey(key2)) { if (levelOneLock) { Monitor.Exit(levelOne); } return(false); } else { levelOne.Add(key2, value); if (levelOneLock) { Monitor.Exit(levelOne); } } } else { this.dataCopy.Add(key1, (levelOne = new LevelOne())); levelOne.Add(key2, value); if (topLevelLock) { Monitor.Exit(this.dataCopy); } } return(true); }
/// <summary> /// Adds the <paramref name="value"/> with the keys /// <paramref name="key1"/>, <paramref name="key2"/>. /// </summary> /// <param name="key1">The <typeparamref name="TKey1"/> which /// is the first key of the <paramref name="value"/> /// to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/>.</param> /// <param name="key2">The <typeparamref name="TKey2"/> which /// is the second key of the <paramref name="value"/> /// to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/>.</param> /// <param name="value">The <typeparamref name="TValue"/> to add to the <see cref="MultikeyedDictionary{TKey1, TKey2, TValue}"/>.</param> public void Add(TKey1 key1, TKey2 key2, TValue value) { // Declare the locals relative to the different levels. LevelOne levelOne; /* ------------------------------------------------------\ | Check each level individually, if the key set is | | already present, throw an the appropriate exception. | \------------------------------------------------------ */ if (((object)(key1)) == null) { throw new ArgumentNullException("key1"); } bool topLevelLock = false; Monitor.Enter(this.dataCopy, ref topLevelLock); if (this.dataCopy.TryGetValue(key1, out levelOne)) { if (topLevelLock) { Monitor.Exit(this.dataCopy); } if (((object)(key2)) == null) { throw new ArgumentNullException("key2"); } bool levelOneLock = false; Monitor.Enter(levelOne, ref levelOneLock); if (levelOne.ContainsKey(key2)) { if (levelOneLock) { Monitor.Exit(levelOne); } throw new InvalidOperationException(); } else { levelOne.Add(key2, value); if (levelOneLock) { Monitor.Exit(levelOne); } } } else { this.dataCopy.Add(key1, (levelOne = new LevelOne())); levelOne.Add(key2, value); if (topLevelLock) { Monitor.Exit(this.dataCopy); } } }
/// <summary> /// Returns/sets the value with the <paramref name="key1"/>, <paramref name="key2"/>, <paramref name="key3"/>, <paramref name="key4"/> provided. /// </summary> /// <param name="key1">The <typeparamref name="TKey1"/> which /// is the first key of the element to set/retrieve.</param> /// <param name="key2">The <typeparamref name="TKey2"/> which /// is the second key of the element to set/retrieve.</param> /// <param name="key3">The <typeparamref name="TKey3"/> which /// is the third key of the element to set/retrieve.</param> /// <param name="key4">The <typeparamref name="TKey4"/> which /// is the fourth key of the element to set/retrieve.</param> public TValue this[TKey1 key1, TKey2 key2, TKey3 key3, TKey4 key4] { get { LevelOne levelOne; LevelTwo levelTwo; LevelThree levelThree; if (((object)(key1)) == null) { throw new ArgumentNullException("key1"); } bool topLevelLock = false; Monitor.Enter(this.dataCopy, ref topLevelLock); if (this.dataCopy.TryGetValue(key1, out levelOne)) { if (topLevelLock) { Monitor.Exit(this.dataCopy); } if (((object)(key2)) == null) { throw new ArgumentNullException("key2"); } bool levelOneLock = false; Monitor.Enter(levelOne, ref levelOneLock); if (levelOne.TryGetValue(key2, out levelTwo)) { if (levelOneLock) { Monitor.Exit(levelOne); } if (((object)(key3)) == null) { throw new ArgumentNullException("key3"); } bool levelTwoLock = false; Monitor.Enter(levelTwo, ref levelTwoLock); if (levelTwo.TryGetValue(key3, out levelThree)) { TValue value; if (levelTwoLock) { Monitor.Exit(levelTwo); } if (((object)(key4)) == null) { throw new ArgumentNullException("key4"); } bool levelThreeLock = false; Monitor.Enter(levelThree, ref levelThreeLock); if (levelThree.TryGetValue(key4, out value)) { if (levelThreeLock) { Monitor.Exit(levelThree); } return(value); } else { if (levelThreeLock) { Monitor.Exit(levelThree); } throw new SubKeyNotFoundException("key4"); } } else { if (levelTwoLock) { Monitor.Exit(levelTwo); } throw new SubKeyNotFoundException("key3"); } } else { if (levelOneLock) { Monitor.Exit(levelOne); } throw new SubKeyNotFoundException("key2"); } } else { if (topLevelLock) { Monitor.Exit(this.dataCopy); } throw new SubKeyNotFoundException("key1"); } } set { LevelOne levelOne; LevelTwo levelTwo; LevelThree levelThree; if (((object)(key1)) == null) { throw new ArgumentNullException("key1"); } bool topLevelLock = false; Monitor.Enter(this.dataCopy, ref topLevelLock); if (this.dataCopy.TryGetValue(key1, out levelOne)) { if (topLevelLock) { Monitor.Exit(this.dataCopy); } if (((object)(key2)) == null) { throw new ArgumentNullException("key2"); } bool levelOneLock = false; Monitor.Enter(levelOne, ref levelOneLock); if (levelOne.TryGetValue(key2, out levelTwo)) { if (levelOneLock) { Monitor.Exit(levelOne); } if (((object)(key3)) == null) { throw new ArgumentNullException("key3"); } bool levelTwoLock = false; Monitor.Enter(levelTwo, ref levelTwoLock); if (levelTwo.TryGetValue(key3, out levelThree)) { if (levelTwoLock) { Monitor.Exit(levelTwo); } if (((object)(key4)) == null) { throw new ArgumentNullException("key4"); } bool levelThreeLock = false; Monitor.Enter(levelThree, ref levelThreeLock); if (levelThree.ContainsKey(key4)) { if (levelThreeLock) { Monitor.Exit(levelThree); } levelThree[key4] = value; } else { levelThree.Add(key4, value); if (levelThreeLock) { Monitor.Exit(levelThree); } } } else { levelTwo.Add(key3, (levelThree = new LevelThree())); levelThree.Add(key4, value); if (levelTwoLock) { Monitor.Exit(levelTwo); } } } else { levelOne.Add(key2, (levelTwo = new LevelTwo())); levelTwo.Add(key3, (levelThree = new LevelThree())); levelThree.Add(key4, value); if (levelOneLock) { Monitor.Exit(levelOne); } } } else { this.dataCopy.Add(key1, (levelOne = new LevelOne())); levelOne.Add(key2, (levelTwo = new LevelTwo())); levelTwo.Add(key3, (levelThree = new LevelThree())); levelThree.Add(key4, value); if (topLevelLock) { Monitor.Exit(this.dataCopy); } } } }