• No results found

Un objeto de un tipo delegado se crea exactamente igual que un objeto de cualquier clase sólo que en su constructor ha de pasársele el nombre del método cuyo código almacenará. Este método puede tanto ser un método estático como uno no estático. En el primer caso se indicaría su nombre con la sintaxis <nombreTipo>.<nombreMétodo>, y en el segundo se indicaría con <objeto>.<nombreMétodo>

Para llamar al código almacenado en el delegado se usa una sintaxis similar a la de las llamadas a métodos, sólo que no hay que prefijar el objeto delegado de ningún nombre de tipo o de objeto y se usa simplemente <objetoDelegado>(<valoresParémetros>)

El siguiente ejemplo muestra cómo crear un objeto delegado de tipo D, asociarle el código de un método llamado F y ejecutar dicho código a través del objeto delegado:

using System;

delegate void D(int valor); class EjemploDelegado {

public static void Main() {

D objDelegado = new D(F); objDelegado(3); }

public static void F(int x) {

Console.WriteLine( “Pasado valor {0} a F()”); }

}

La ejecución de este programa producirá la siguiente salida por pantalla: Pasado valor 3 a F()

Nótese que para asociar el código de F() al delegado no se ha indicado el nombre de este método estático con la sintaxis <nombreTipo>.<nombreMétodo> antes comentada. Esto se debe a que no es necesario incluir el <nombreTipo>. cuando el método a asociar a un delegado es estático y está definido en el mismo tipo que el código donde es asociado En realidad un objeto delegado puede almacenar códigos de múltiples métodos tanto estáticos como no estáticos de manera que una llamada a través suya produzca la ejecución en cadena de todos ellos en el mismo orden en que se almacenaron en él. Nótese que si los métodos devuelven algún valor, tras la ejecución de la cadena de llamadas sólo se devolverá el valor de retorno de la última llamada.

llamar desde un tipo a métodos privados de otros tipos que estén almacenados en un delegado por accesible desde el primero tal y como muestra el siguiente ejemplo:

using System; public delegate void D(); class A

{

public static D obj; public static void Main() { B.AlmacenaPrivado(); obj(); } } class B {

private static void Privado()

{ Console.WriteLine(“Llamado a método privado”); } public static void AlmacenaPrivado()

{ A.obj += new D(Privado); } }

La llamada a AlmacenaPrivado en el método Main() de la clase A provoca que en el campo delegado obj de dicha clase se almacene una referencia al método privado Privado() de la clase B, y la instrucción siguiente provoca la llamada a dicho método privado desde una clase externa a la de su definición como demuestra la salida del programa:

Llamado a método privado

Para añadir nuevos métodos a un objeto delegado se le aplica el operador += pasándole

como operando derecho un objeto delegado de su mismo tipo (no vale de otro aunque admita los mismos tipos de parámetros y valor de retorno) que contenga los métodos a añadirle, y para quitárselos se hace lo mismo pero con el operador -=. Por ejemplo, el

siguiente código muestra los efectos de ambos operadores: using System;

delegate void D(int valor); class EjemploDelegado {

public string Nombre;

EjemploDelegado(string nombre) {

Nombre = nombre; }

public static void Main() {

EjemploDelegado obj1 += new EjemploDelegado(“obj1”); D objDelegado = new D(f);

El lenguaje de programación C# Tema 12: Delegados y eventos

objDelegado += new D(obj1.g); objDelegado(3); objDelegado -= new D(obj1.g); objDelegado(5);

}

public void g(int x) {

Console.WriteLine(“Pasado valor {0} a g() en objeto {1}”, x, Nombre); }

public static void f(int x) {

Console.WriteLine( “Pasado valor {0} a f()”, x); }

}

La salida producida por pantalla por este programa será: Pasado valor 3 a f()

Pasado valor 3 a g() en objeto obj1 Pasado valor 5 a f()

Como se ve, cuando ahora se hace la llamada objDelegado(3) se ejecutan los códigos de los dos métodos almacenados en objDelegado, y al quitársele luego uno de estos códigos la siguiente llamada sólo ejecuta el código del que queda. Nótese además en el ejemplo como la redefinición de + realizada para los delegados permite que se pueda inicializar

objDelegado usando += en vez de =. Es decir, si uno de los operandos de + vale null no se produce ninguna excepción, sino que tan sólo no se añade ningún método al otro.

Hay que señalar que un objeto delegado vale null si no tiene ningún método asociado,

ya sea porque no se ha llamado aún a su constructor o porque los que tuviese asociado se le hayan quitado con -=. Así, si al Main() del ejemplo anterior le añadimos al final:

objDelegado -= new D(f); objDelegado(6);

Se producirá al ejecutarlo una excepción de tipo System.NullReferenceException

indicando que se ha intentado acceder a una referencia nula.

También hay que señalar que para que el operador -= funcione se le ha de pasar como

operador derecho un objeto delegado que almacene algún método exactamente igual al método que se le quiera quitar al objeto delegado de su lado izquierdo. Por ejemplo, si se le quiere quitar un método de un cierto objeto, se le ha de pasar un objeto delegado que almacene ese método de ese mismo objeto, y no vale que almacene ese método pero de otro objeto de su mismo tipo. Por ejemplo, si al Main() anterior le añadimos al final:

objDelegado -= new g(obj1.g); objDelegado(6);

Entonces no se producirá ninguna excepción ya que el -= no eliminará ningún método

de objDelegado debido a que ese objeto delegado no contiene ningún método g() procedente del objeto obj1. Es más, la salida que se producirá por pantalla será:

Pasado valor 3 a g() en objeto obj1 Pasado valor 5 a f()

Pasado valor 6 a f()

Related documents