[.NET] Qué es un Delegate y su implementación en C# (y II).


En el anterior post vimos la definición de delegate, qué características tiene y vimos también las diferentes formas de instanciarlos. En el siguiente post veremos qué es un Multicast delegate y los diferentes tipos de Generic delegate.

¿Qué es un Multicast delegate?

Un Multicast delegate es un delegado el cual mantiene referencias a más de un método. Este tipo de delegado debe contener únicamente métodos que devuelvan un void, de otro modo se lanzará una excepción en tiempo de ejecución. Al invocar al delegado, se ejecutarán todos los métodos asociados en el mismo orden en el cual fueron agregados al delegado.

Para agregar métodos al delegado se emplea el operador  ‘+=’ y para eliminar métodos del delegado se emplea el operador ‘-=’. Un mismo método se puede añadir a un objeto delegado más de una vez.

Veamos un ejemplo de Multicast delegate:

using System;

public delegate void MiDelegadoMultiCast(int i); 
 
public class Test
{
  public static void Main()
  {
    MiClase miClase = new MiClase();
   
    // instanciamos un delegado. Observa que el método MiMetodo1 de la clase 
    // MiClase cumple con la firma definida en el delegado
    MiDelegadoMultiCast delegado = miClase.MiMetodo1;
    delegado(83); // Se hace la llamada al delegado
    
    // agregamos ahora el Metodo2 
    delegado += miClase.MiMetodo2;
    // Se hace la llamada al delegado y se ejecutarán en orden secuencial ambos métodos
    delegado(55); 

    // eliminamos ahora el Metodo1 
    delegado -= miClase.MiMetodo1;
    // Se hace la llamada al delegado y se ejecutará únicamente el Método2
    delegado(14); 
   
  }
}
 
public class MiClase
{
  public void MiMetodo1(int i)
  {
    Console.WriteLine("El valor pasado al METODO1 como parámetro es: {0}", i);
  }
  public void MiMetodo2(int i)
  {
    Console.WriteLine("El valor pasado al METODO2 como parámetro es: {0}", i);
  }
}

¿Qué es un Generic delegate?

Los Generic Delegate no requieren la definición de una instancia de un delegado para invocar a los métodos.

Existen tres tipos de Generic delegate:

Generic Delegate: Func

El delegado Func define un método que puede ser llamado con argumentos y devolver un valor. Existen varias sobrecargas de este delegado que podéis ver en la MSDN.

Un ejemplo básico de este delegado podría ser:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Test
{
  public static void Main()
  {
    // Definir el delegado Func con parámetro de entrada de tipo int y devuelve un string
    Func<int, string> showIntToString = delegate(int i)
    {
      return i.ToString();
    };

    // Definir el delegado Func con parámetro de entrada de tipo string y devuelve un int
    Func<string, int> showStringToInt = s => 
    {
      return int.Parse(s);
    };

    // Llamar a los delegados
    Console.WriteLine(showIntToString(16));
    Console.WriteLine(showStringToInt("55")); 
  }
}

Generic Delegate: Action

El delegado Action define un método que puede ser llamado con argumentos pero NO devuelve un valor. Existen varias sobrecargas de este delegado que podéis ver en la MSDN.

Un ejemplo básico de este delegado podría ser:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Test
{
  public static void Main()
  {
    // Definir el delegado Action con parámetro de entrada de tipo int
    Action<int> showIntToString = delegate(int i)
    {
      Console.WriteLine("El valor pasado al delegado como parámetro es: {0}", i);
    };

    // Definir el delegado Action con parámetro de entrada de tipo string
    Action<string> showStringToInt = s => 
    {
      Console.WriteLine("El valor pasado al delegado como parámetro es: {0}", s);
    };

    // Llamar a los delegados
    showIntToString(16);
    showStringToInt("55"); 
  }
}

Generic Delegate: Predicate

El delegado Predicate define un método que puede ser llamado con argumentos pero SIEMPRE devuelve un valor de tipo bool. Existen varias sobrecargas de este delegado que podéis ver en la MSDN.

Un ejemplo básico de este delegado podría ser:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Test
{
  public static void Main()
  {
    string validNumber = "28";
    string invalidNumber = "28z";

    // Definir el delegado Predicate con parámetro de entrada de string
    Predicate<string> isValidNumber = d => IsNumber(d);

    if (isValidNumber(validNumber))
    {
      Console.WriteLine("El número {0} es válido", validNumber);
    }
    else
    {
      Console.WriteLine("El número {0] NO es válido", validNumber);
    }   
   
    if (isValidNumber(invalidNumber))
    {
      Console.WriteLine("El número {0} es válido", invalidNumber);
    }
    else
    {
      Console.WriteLine("El número {0} NO es válido", invalidNumber);
    }
  }

  private static bool IsNumber(string number)
  {
    Decimal d;
    return Decimal.TryParse(number, out d);
  }
}

Diferencias entre delegados genéricos

La siguiente tabla resume las diferencias entre los tipos de delegados genéricos que ya hemos visto:

Func Action Predicate
Argumentos SI SI SI
Devuelve valor SI NO SI (Boolean)

Para la realización de estos artículos he tomado como referencia el siguiente enlace de MSDN:

Delegates (C# Programming Guide).

Anuncios

Un comentario en “[.NET] Qué es un Delegate y su implementación en C# (y II).

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s