
he Dictionary class in .NET 2.0's System.Colllections.Generic namespace provides the ability to create a strongly-typed dictionary where both the
Keys and
Values collections can accept
any object-type. This capability enables novel solutions to typical programming problemsfor example in coordinating the current selection where multiple controls represent the same data, such as synchronizing selection between a ListView and TreeView.
This article presents a few simple and practical examples of using generic dictionaries. It concludes with one "far-out" example (that
could be used to implement late binding) and that I hope will get you excited about the power of these dictionaries and trigger creative ideas in your own work.
When you first encounter .NET 2.0's new generic facilities, you may assume, as I did, that these are some very neat tools for easily and flexibly creating strongly typed collections; for avoiding casting, boxing, and unboxing in collections or lists; and for ensuring type-safety in your code so that errors are flagged at compile time, rather than erupting at run-time.
What You Need |
You need NET 2.0 to run the examples. I created them with Visual Studio 2005, but they should be easily replicable in any IDE that supports .NET 2.0, and has access to the standard TreeView and ListView controls. |
The List and Collection objects in the Systems.Collections.Generic namespace give you all that functionality, and amplify your programming power by letting you create custom types using the generic type designator
<T>. You can use the Comparer and Enumerator facilities to make custom generic types both enumerable and comparable.
More advanced structures such as Queue and Stack give you a head start on modeling typical data structures, and SortedDictionary gives you the tools for a Dictionary type with an inherent sort order.
What surprised and delighted me when I finally got around to looking at the capabilities of the generic Dictionary class was to find that it was much more flexible than I thought it would be. Having once programmed extensively in PostScript, which had similarly flexible dictionaries, this flexibility made me think of late-binding scenarios where, by either changing a value associated with a key, or changing the dictionary in which you looked up the key, you could manipulate semantic contexts. In fact a "dictionary stack" is, internally, how PostScript manipulates name-look-up and syntactic scoping; let me know if you find the party where you can bring
that into the conversation!
Building a Generic Dictionary
To start,
download and unzip the sample code, and open the
GD_Example_1 project.
Open the code-behind
Form1.cs file and check to make sure you see the declaration:
using System.Collections.Generic;
Either in your head, or looking at the code, visualize/observe two controls on the form: a TreeView and a ListView. Each contains a set of 10 items. Now, add a generic dictionary declaration:
private Dictionary nodeDictionary =
new Dictionary();
You now have a dictionary named
nodeDictionary in which the
Keys collection contains a set of TreeNode objects and the
Values collection holds ListViewItems.
What (
I hope) just came into your mind was all the times you may have manipulated the
Tag property of control "inner-collection-objects" such as TreeNodes and ListViewItems so that when a user selected a TreeNode you could find and select a corresponding ListViewItem in the ListViewand vice-versa. You also probably remember that every time you accessed the
Tag property, you had to
cast the value to the proper object type (and casting, as we all know, is very expensive, and contributes to global warming). In other words, to get the corresponding ListViewItem stored in the
Tag property of a TreeNode you had to write:
You probably remember using the Tag property to coordinate control selection, but until generics, you had to cast the value to the proper object type.
|
|
ListViewItem currentListViewItem = (ListViewItem)
currentTreeNode.Tag;
Now you can use the
nodeDictionary to look up a ListViewItem using a TreeNode as the key with no casting required:
ListViewItem currentListViewItem =
nodeDictionary[currentTreeNode];
See the sidebar
Getting Under the Hood of Generic Dictionaries for more information on the way generic dictionaries work.