IDictionary
The nongeneric IDictionary interface is the same in principle as
IDictionary<TKey,TValue>, apart from two important functional differences.
It’s important to be aware of these differences, because IDictionary appears in
legacy code (including the .NET Framework itself in places):
• Retrieving a nonexistent key via the indexer returns null (rather than throwing
an exception).
• Contains tests for membership rather than ContainsKey.
Enumerating over a nongeneric IDictionary returns a sequence of DictionaryEn
try structs:
public struct DictionaryEntry
{
public object Key { get; set; }
public object Value { get; set; }
}
Dictionary<TKey,TValue> and Hashtable
The generic Dictionary class is one of the most commonly used collections (along
with the List<T> collection). It uses a hashtable data structure to store keys and
values, and it is fast and efficient.
The nongeneric version of Dictionary<TKey,TValue> is
called Hashtable; there is no nongeneric class called Diction
ary. When we refer simply to Dictionary, we mean the generic
Dictionary<TKey,TValue> class.
Dictionary implements both the generic and nongeneric IDictionary interfaces, the
generic IDictionary being exposed publicly. Dictionary is, in fact, a “textbook” im-
plementation of the generic IDictionary.
Here’s how to use it:
var d = new Dictionary<string, int>();
d.Add("One", 1);
d["Two"] = 2; // adds to dictionary because "two" not already present
d["Two"] = 22; // updates dictionary because "two" is now present
d["Three"] = 3;
Console.WriteLine (d["Two"]); // Prints "22"
Console.WriteLine (d.ContainsKey ("One")); // true (fast operation)
Console.WriteLine (d.ContainsValue (3)); // true (slow operation)
int val = 0;
if (!d.TryGetValue ("onE", out val))
Console.WriteLine ("No val"); // "No val" (case sensitive)
// Three different ways to enumerate the dictionary:
foreach (KeyValuePair<string, int> kv in d) // One ; 1
Console.WriteLine (kv.Key + "; " + kv.Value); // Two ; 22
// Three ; 3
foreach (string s in d.Keys) Console.Write (s); // OneTwoThree
Console.WriteLine();
foreach (int i in d.Values) Console.Write (i); // 1223
Its underlying hashtable works by converting each element’s key into an integer hash
code—a pseudounique value—and then applying an algorithm to convert the hash
code into a hash key. This hash key is used internally to determine which “bucket”
an entry belongs to. If the bucket contains more than one value, a linear search is
performed on the bucket. A hashtable typically starts out maintaining a 1:1 ratio of
buckets to values (a 1:1 load factor), meaning that each bucket contains only one
value. However, as more items are added to the hashtable, the load factor dynami-
cally increases, in a manner designed to optimize insertion and retrieval performance
as well as memory requirements.
A dictionary can work with keys of any type, providing it’s able to determine equality
between keys and obtain hash codes. By default, equality is determined via the key’s
object.Equals method, and the pseudounique hash code is obtained via the key’s
GetHashCode method. This behavior can be changed, either by overriding these
methods or by providing an IEqualityComparer object when constructing the dic-
tionary. A common application of this is to specify a case-insensitive equality com-
parer when using string keys:
var d = new Dictionary<string, int> (StringComparer.OrdinalIgnoreCase);
No comments:
Post a Comment