Tuesday, September 12, 2006

Dictionaries of methods in C#

This article is a follow up of my previous article arrays of methods in C#, as noted by some of the commenters, it is possible to implement this technique using dictionaries, Steven even (Steven even... kinda funny... anyway, where was I? oh ok) posted a comment with the full implementation of my code using dictionaries, I just wanted to hightlight some of the differences and perhaps give you a hint on when to use either one (although it should be obvious, but I've learnt that there is no such thing as obvious)

Since the dictionaries implement a <Key, Value> way of storing stuff, you can store an int or a string, or any other type as the key as long as you don't have duplicated entries, and on the value you can store the pointer to the method you want to execute, when using arrays you are limited to use types that can be converted to integers for the index, with dictionaries you could use other types as the index.

let's see the last example and how it changes, the changes -as you will see- are pretty minimal to switch between the two

- The delegate declaration doesn't change

- now instead of an array, we have a dictionary, it looks something like this:

Dictionary<int, AddStringDelegate> addStringMethods;

- The methods declaration stay the same


- Adding the methods to our dictionary is just a little bit different:

addStringMethods = new Dictionary<int, AddStringDelegate>(4);
addStringMethods.Add((int)StringType.Type1, new AddStringDelegate(AddStringType1));
addStringMethods.Add((int)StringType.Type2, new AddStringDelegate(AddStringType2));
addStringMethods.Add((int)StringType.Type3, new AddStringDelegate(AddStringType3));
addStringMethods.Add((int)StringType.Type4, new AddStringDelegate(AddStringType4));

- The implementation to use the methods remains exactly the same

public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}

We're done! so we just had to change a couple places and we are now using dictionaries of methods instead of arrays.


So when do I use dictionaries over arrays? basically, when you need it, arrays are a lot more simple and lightweight, dictionaries add weight but give you a lot more flexibility, for example if you want to use a string as the index to access your method, then the dictionary is the way to go; dictionaries also allow you to add/remove items from it, I don't know that it would be a good idea to apply that in this case, but you can do it. If you can get an integer index I would use the array instead, you don't really need the dictionary in that case.


If no one (out of my 3 readers J) beats me to it, I'll run some tests using both approaches and see if there is any relevant difference in speed and I'll post the results here. If you do the tests, and you blog about it, and I find out, I'll put a link here just as a follow up to this


Here's the full code, play with it, break it, expand it, make it better

class FileGeneratorBase {

Dictionary<int, AddStringDelegate> addStringMethods;

public FileGeneratorBase() {
addStringMethods = new Dictionary<int, AddStringDelegate>(4);
addStringMethods.Add((int)StringType.Type1, new AddStringDelegate(AddStringType1));
addStringMethods.Add((int)StringType.Type2, new AddStringDelegate(AddStringType2));
addStringMethods.Add((int)StringType.Type3, new AddStringDelegate(AddStringType3));
addStringMethods.Add((int)StringType.Type4, new AddStringDelegate(AddStringType4));
}

public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}
void AddStringType1(string someValue) {
OutputText(string.Format("String Type 1: {0}", someValue));
}
void AddStringType2(string someValue) {
OutputText(string.Format("String Type 2: {0}", someValue));
}
void AddStringType3(string someValue) {
OutputText(string.Format("String Type 3: {0}", someValue));
}
void AddStringType4(string someValue) {
OutputText(string.Format("String Type 4: {0}", someValue));
}
void OutputText(string someValue) {
Console.WriteLine(someValue);
}
}

class Program {
static void Main(string[] args) {
//*** Arrays of methods demo
FileGeneratorBase fg = new FileGeneratorBase();
fg.AddString("some value", StringType.Type1);
fg.AddString("some other value", StringType.Type2);
fg.AddString("one last value", StringType.Type3);
fg.AddString("testing out of bounds", StringType.Type4);
Console.ReadLine();
}
}

on my next article I'll show you the implementation of this technique applied to the simple factory pattern just to close the loop.

1 comment:

Steven said...

This post was in the pipeline for a long time, but a post on Eber Irigoyen's blog made me speed things up a bit...