Monday, August 28, 2006

Hiding generics complexity part II

on previous articles I talked about complex generic types

Multidimensional generics

and how to make those types more readable by using aliases

Hiding generics complexity

    using System.Collections.Generic;
using FilesList = List<string>;
using FoldersWithFiles = Dictionary<string, List<string>>;
using ComputersWithFiles = Dictionary<string, Dictionary<string, List<string>>>;

Here is another technique to accomplish readable code while still using generics.


We can subclass the generics in this way:

    class FilesList2 : List<string> { }
class FoldersWithFiles2 : Dictionary<string, List<string>> { };
class ComputerFiles2 : Dictionary<string, Dictionary<string, List<string>>> { }
class ComputersWithFiles2 : Dictionary<string, Dictionary<string, List<string>>> { }

The code to use them is pretty much the same as when we were using aliased generics, but there is a little "problem", KeyValuePair is a struct and as such it doesn't support inheritance, which means we can't apply this technique to this type, so we can combine aliased types for the KeyValuePair and sub-classing for the rest


This brings us to another point, when we have code like this:

Console.WriteLine("List of Directories with files");
FoldersWithFiles2 foldersWithFiles = GetFoldersWithFiles();
foreach (FoldersWithFilesPair kv in foldersWithFiles) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv.Key));
ListFiles((FilesList2)kv.Value);
}

If we want to use FoldersWithFilesPair.Value as a FilesList2 type we have to typecast it, this is because FilesList2 is a new type and FoldersWithFilesPair.Value is a List<string>; remember that C# is a type-safe language.


Subclassing the generic types in this way can give you more benefits than simply more readable code, as any other class they can implement methods so you can assign them more specific tasks/methods that reflect more accurately their responsibility


There is a big difference betwee using aliased generics and subclassed generics, aliased types are the exact same type, just with a different name, subclassed generics are a new name and a new type.


This is it for now, you now have a new tool in your toolbox, as with everything else in life, don't abuse it!


Hope to see some code where people are using these techniques


as promissed, here is the full source code, the code is free as in LPGL

No comments: