Each Map class (Map<K, V>, Map<K1, K2, V>, and Map<K1, K2, K3, V>) implement the following class and interfaces.
  • IMap<>
    • Map<K, V> is an IMap<K, V>, Map<K1, K2, V> is an IMap<K1, K2, V>, and Map<K1, K2, K3, V> is an IMap<K1, K2, K3, V>
  • MapBase<>
    • Implements DictionaryCommonBase<>
  • IDictionary
    • Map<K, V> is an IDictionary<K, V>, Map<K1, K2, V> is an IDictionary<K1, IDictionary<K2, V>>, and Map<K1, K2, K3, V> is an IDictionary<K1, IDictionary<K2, IDictionary<K3, V>>

If you prefer to not use the map class types as reference identifier types, it is recommended that you use the IMap interfaces. If it is needed, all Map types also implement the IDictionary interface. However, due to the potential performance loss for treating a Map as an IDictionary (see Performance), it is recommended to not use the IDictionary interface unless you need to.

public void Foo<K1, K2, V>(IMap<K1, K2, V> map)

public void Bar<K1, K2, V>(IDictionary<K1, IDictionary<K2, V>> dictionary)

public void Baz()
  var map = new Map<int, int, int>();


The Map classes represent 1 or more keys to a single value. When possible, the developer should use the keys as sets, and not trees.

Set of keys example (multidimensional-notation)

var map = new Map<int, int, int, int>();
map[1, 2, 3] = 4;

int result = map[1, 2, 3];

Tree of keys example (jagged-notation)

var map = new Map<int, int, int, int>();
map[1][2][3] = 4;

int result = map[1][2][3];

Both of the above examples (and combinations thereof) will accomplish the exact same thing. Much care was taken, and about 140 tests were made (at the time of this writing), in effort to prove the functionality of the Map classes. It was always part of the feature plan to allow for jagged notation. Note, however, that the computational complexity behind allowing for child-map access (jagged notation, or whatever I may feel like calling it) has an unfortunate performance hit. Stress testing has found that jagged notation increases read and write times when compared to multidimensional reads and writes (as shown in the first example). Each layer of jagged access (e.g. map[1][2] vs map[1, 2]), adds approximately the same amount of time as a single read/write on the same map. Thus, map[1][2] would take 2x as long as map[1, 2], and map[1][2][3] would take 3x as long as map[1, 2, 3].

Note that these read/write times are extremely short. Over billions of read/write actions, the additional overhead of using map vs dictionary has been found to add <1%. The performance consideration herein is of great value to those using multi-key maps where performance and map access is a potential bottleneck.


A special note on 'Remove'. Removing a key set also removes the parent key if there are no remaining siblings.
var map = new Map<int, int, int, int>();
map[1, 2, 3] = 4;
map[1, 2, 4] = 5;
Assert.IsTrue(map.Remove(1, 2, 3));

Assert.IsTrue(map.ContainsKey(1, 2));
Assert.IsTrue(map.ContainsKey(1, 2, 4));

Assert.IsTrue(map.Remove(1, 2, 4));

Assert.IsFalse(map.ContainsKey(1, 2));

Last edited Jun 24, 2011 at 9:52 PM by payonel, version 9


No comments yet.