Roberto Sánchez Programador/Desarrollador .NET

Delegados.

Un delegado se pueden definir como un nuevo tipo que hace referencia a un método. Es un tipo de clase muy especializado y son muy similares a los punteros de C++, pero orientados a objetos. Aceptan modificadores de acceso 'private', 'public', 'protected' e 'internal', y parámetros.

A un delegado se le puede asignar cualquier método que coincida con el prototipo del del delagado, tanto por el tipo como por los parámetros.

public delegate bool SortOrder(double x, double y);

Al delegado 'SortOrder' se le deberá asignar un método que contenga dos parámetros de tipo 'double' y una salida de resultado de tipo 'bool':

public static bool CompareTwoElements(double x, double y)
{
    return x > y;
}
SortOrder sortOrderDelegate = new SortOrder (CompareTwoElements);

Vamos a por un ejemplo funcional. En la siguiente clase 'Vector' añadiremos un método 'Sort' que ordenará los elementos almacenados por su atributo 'vector'. Dicha ordenación se realizará según indique el método asignado al delegado pasado como argumento.

public void Sort(SortOrder sortOrderDelegate)
{
    int i, k;
    double x;
    for (i = 1; i < nElements; i++) // Desde el segundo elemento.
    {
        x = vector[i];
        while (k >= 0 && sortOrderDelegate(x, vector[k]))
        {
            vector[k + 1] = vector[k]; // Hacer hueco para insertar.
            k++;
        }
        vector[k + 1] = x; // Insertar 'x' en su lugar.
    }
}

Al asignar el método al delegado, éste se comporta como el método. Así, la forma de invocar al delegado es la misma forma que se utilizaría para invocar al método que tiene asignado. En otras palabras, cuando se ejecuta un delegado éste le pasa al método que tiene asignado los parámetros especificados para que se ejecute. Por lo tanto, el valor de retorno del delegado será el que devuelva el método que tiene asignado.

Vamos a implementar el delegado. Creamos un objeto 'vector1' de la clase 'Vector' deseamos ordenarlo de manera descendente. Según el código fuente del método 'Sort', el delegado debe hacer referencia a un método que defina el tipo de comparación que deseamos hacer con respecto a dos elementos de 'vector':

using System;
public class Program
{
    public static void ViewVector(Vector v)
    {
        int ne = v.Length();
        for (int i = 0; i < ne; i++)
            Console.Write(v.ValueIn(i) + " ");
        Console.WriteLine();
    }
    public static bool CompareTwoElements(double x, double y)
    {
        return x > y;
    }
    public static void Main()
    {
        double[] x = new double[] { 1, 3, 5, 7, 2, 4, 6 };
        Vector vector1 = new Vector(x);
        vector1.Sort(CompareTwoElements);
        ViewVector(vector1);
    }
}

Ten encuenta que la llamada a 'Sort' de 'vector1' es la forma simplificada de:

vector1.Sort(new SortOrder(CompareTwoElements));

Si el método asignado al delegado no fuera 'satatic', entonces el delegado haría referencia tanto al objeto como al método. Por ejemplo:

public bool CompareTwoElements(double x, double y)
{
    return x > y;
}
public static void Main()
{
    Program program = new Program();
    SortOrder sortOrderDelegate = program.CompareTwoElements;
    // ...
}

Por últimno, ten en cuenta que los delegados derivan de la clase 'Delegate' del espacio de nombres 'System' del .NET Framework, y sólo los compiladores pueden derivar de esa clase de manera explícita. Por ello, tú deberás emplear la palabra clave 'delegate'.