Tuesday, September 12, 2006

Dictionarios de metodos en C#

Este articulo es en seguimiento a mi articulo anterior arreglos de metodos en C#, en algunos de los comentarios mencionaron que es posible implementar esta tecnica usando diccionarios, alguien por ahi incluso puso el codigo completo usando diccionarios, de cualquier manera queria subrayar algunas de las diferencias y señalar donde podriamos usar una u otra alternativa (que deberia ser obvia, pero he aprendido que no hay tal cosa como algo obvio)

En los diccionarios podemos guardar datos de la forma <Key, Value>, asi que podemos guardar un int, string o lo que sea, en el Key, y en el value podemos poner el puntero hacia el metodo que queremos ejecutar; en contraste, cuando usamos arreglos de metodos, estamos limitados a usar tipos de datos que pueden ser convertidos a enteros para accesar nuestros metodos.

Vamos a ver el ejemplo previo y como cambia para adaptarlo a usar diccionarios, los cambios -como veran- son minimos para migrar de una a otra alternativa

- La declaracion del delegado no cambia

- Ahora, en vez de un arreglo, tenemos un diccionario, algo asi mas o menos:

Dictionary<int, AddStringDelegate> addStringMethods;

- La declaracion de los metodos es la misma


- El codigo para agregar los metodos al diccionario es un poquito diferente:

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);
}

Listo! asi que solo tuvimos que cambiar un par de cosas y ya estamos usando diccionarios en vez de arreglos.


Entonces, cuando debo usar diccionarios en vez de arreglos? basicamente, cuando los necesites; los arreglos son mucho mas simples y livianos, los diccionarios agregan algo de peso pero te dan mas flexibilidad, por ejemplo si quieres usar un string para accesar el metodo, entonces puedes usar el diccionario; los diccionarios tambien te permiten agregar/borrar, ahorita no se me ocurre porque querrias hacer eso, pero se puede hacer. Yo diria que si tienes un numero entero con el que puedes accesar el metodo que necesitas, usa el arreglo, realmente no necesitas usar diccionarios en ese caso.


Si nadie (de mis 3 lectores) me gana, correre unas pruebas usando ambas opciones y vere si hay alguna diferencia relevante en velocidad, y posteare los resultados aqui. Si tu haces las pruebas, y lo pones en tu blog, y yo me entero, entonces incluire un link aqui solo para dar seguimiento a esta onda


Aqui esta el codigo completo, quitale, agregale, cambiale, hazlo mejor

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();
}
}

En mi siguiente articulo te mostrare la implementacion de esta tecnica aplicada al patron de creacion simple, solo para cerrar el ciclo en este tema.

No comments: