Monday, August 21, 2006

C# multidimensional generics

You can think of Generics as Arrays on steroids or Collections on steroids or a combination of both, they offer an extensible list of items with type safety; or as MSDN puts it:

Generics allow you to define type-safe data structures, without committing to actual data types.

One thing that I haven't seen much is how you can use multidimensional generics (yup, invented here J), let me explain what I mean

let's say we wanted to store a list of file names, we could do something like:




List<string> filesList = GetFilesList();
ListFiles(filesList);


now, we want a list of directories with the files in them, we could use a bidimensional generic type to keep the directory name on a dictionary key and the list of files on the dictionary value:


Dictionary<string, List<string>> foldersWithFiles = GetFoldersWithFiles();
foreach (KeyValuePair<string, List<string>> kv in foldersWithFiles) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv.Key));
ListFiles(kv.Value);
}


finally, let's say we want a list of computers, with folders that contain files, we can use a multidimensional generic type that has the computer name on a dictionary key, and the folders with files on another dictionary stored as the key:




Dictionary<string, Dictionary<string, List<string>>> ComputerFiles = GetComputerFiles();
foreach (KeyValuePair<string, Dictionary<string, List<string>>> kv in ComputerFiles) {
Console.WriteLine(string.Format("Computer: [{0}]", kv.Key));
foreach (KeyValuePair<string, List<string>> kv1 in kv.Value) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv1.Key));
ListFiles(kv1.Value);
}
}


For the sake of completeness here's the ListFiles function, just so you can see some cool use of generics combined with anonymous delegates:


static void ListFiles(List<string> filesList) {
filesList.ForEach(new Action<string>(delegate(string s) { Console.WriteLine(string.Format(" {0}", s)); }));
}


As you can see, with generics we can create some complex type-safe data structures, however, as always, some people will complain that multidimensional generics become very cryptic;

and you can see it if you did something like:



Dictionary<string, Dictionary<string, List<string>>> ComputerFiles = new Dictionary<string, Dictionary<string, List<string>>>();

in my next post I'll show you a couple techniques you can use to hide the generics complexity while keeping all of their benefits

1 comment:

Anonymous said...

Dictionary>> ComputerFiles = new ...

How to use the CompuerFiles.Add() function?
I tried ComputerFiles.Add(string, string, string) ... doesn't work.