C Sharp (C#) – Usar Delegados – Parte 7

Hacer llamadas asíncronas usando delegados

Hasta el momento hemos hecho llamadas a métodos de forma síncrona por medio de delegados.dos caminos

¿Qué son las llamadas síncrona? Las llamadas a métodos de forma síncrona son las que siguen el patrón común de los programas de pasar a la próxima instrucción cuando se termine de ejecutar un método. Cuando se ejecuta un método se espera a que se termine la ejecución para pasar a la siguiente instrucción, se espera a que se terminen las instrucciones del método para pasar a la siguiente. Estas son las llamadas a métodos de forma síncrona, son las llamadas a métodos que se ocupan comúnmente.

¿Qué son las llamadas asíncronas? En las llamadas a métodos de forma asíncrona no se espera a que se termine la llamada para pasar a la siguiente instrucción, sino que el programa sigue pasando ordenadamente a la siguientes instrucciones sin esperar a que se termine la llamada. Una llamada asíncrona queda en una especie de hilo de ejecución aparte.

Una de las utilidades de las llamadas asíncronas es evitar que las aplicación principal se congele ya que se puede enviar una tarea pesada a que se ejecute de manera asíncrona (en un hilo de ejecución a parte). Con esto se evita a que la ejecución del programa principal se congele mientras hace una tarea pesada.

Se pueden hacer llamadas asíncronas por medio de delegados. Pero este mecanismo tiene una limitación, es que solo es valido para objetos delegados que almacenen un único método, el -objeto delegado síncrona- debe referenciar un solo método, de lo contrario dará un excepción System.ArgumentExceptión . Pero el objeto delegado que va a ser asíncrono puede referenciar a más de un método.  C Sharp cuenta con algunas clases, interfaces, delegados, etc. predefinidas en el espacio de nombres System para manejar las llamadas síncronas y asíncronas.

Tenemos un delegado, con el cual podemos crear un objeto delegado que puede almacenar un método que se quiere que sea asíncrono. El delegado es:

public delegate void AsyncCallback (IAsyncResult ar)

Tenemos una interfaz, la cual almacena información relativa al método que será llamado de forma asíncrona.

public interface System.IAsyncResult

Y tenemos dos métodos BeginInvoke y EndInvoke, que tienen todos los objetos delegados. BeginInvoke nos sirve para invocar el objeto delegado que referencia a un método síncronos y a la vez invocar un objeto delegado que referencia uno o más métodos de forma asíncrona.

IAsyncResult BeginInvoke (<parámetros>, AsyncCallback cb, Object o)

Como vemos el método ‘BeginInvoke’ devuelve un objeto ‘IAsyncResult’ que contiene información relacionada al resultado de la ejecución de los métodos asíncrona, lo veremos en el ejemplo. En ‘<parámetros>’ esta relacionado con los parámetros del tipo delegado al cual se llama con ‘BeginInvoke’. En ‘Object o’ van un objeto opcional que se le quisiera pasar a los métodos que se ejecutan de manera asíncrona.

<tipoRetorno> EndInvoke (<parámetrosRefOut>, IASyncResult ar)

El método ‘EnInvoke’ sirve para recibir el valor de retorno de los métodos que fueron llamados de manera asíncrona, para saber las excepciones (si es que hubieron). Luego veremos más.

Ahora el ejemplo:

// por Writkas
//
// Delegados5_Comentado.cs : Hacer llamadas asíncronas usando delegados
//
// Compilar en Linux con Mono:
//	gmcs Delegados5_Comentado.cs
//
// Compilar en Linux con Mono en C# 5:
//	gmcs -langversion:future Delegados5_Comentado.cs
//
// Ejecutar:
//	mono Delegados5_comentado.exe

// Recordar que en el namespace System están definidos todos las clases para el
// tratamiento de las llamadas asíncrona y también síncrona.
using System;

// Creamos un tipo delegado común y corriente
delegate void DelegadoAsíncronas (string str);

class Test
{
  public static void Main ()
  {
  // Creamos un objeto delegado común 'objDA' y le asignamos el método 'Método'
    DelegadoAsíncronas objDA = new DelegadoAsíncronas (Método1);
  // El objeto 'objDA' solo debe contener un solo método almacenado si luego se quiere
  // hacer una llamada asíncrona.

  // Se crea un objeto 'AsyncCallback' y se le añade un método 'Método2', para luego
  // enviarle este objeto con su método referenciado al objeto delegado 'objDA' que creamos
  // anteriormente.
  // A continuación se indica que es AsyncCallvack :
  // public delegate void AsyncCallback (IAsyncResult ar)
    AsyncCallback objAC = new AsyncCallback (Método2);

  // Almacena información relativa al método que será llamado de forma asíncrona:
  // public interface System.IAsyncResult
  // Se puede saber si el método asíncrona se termino de ejecutar con la propiedad:
  // public  bool IsCompleted [solo lectura]
  // Se puede saber si el método asíncrona se terminó de ejecutar de manera sícrona con:
  // public bool CompletedSyncronously [solo lectura]
    IAsyncResult objIAR;

  // Lanza la llamada al 'Método2' que está contenida en el objeto delegado 'objAC' de
  // manera asíncrona. el 'Método2' se ejecuta de manera asíncrona (en un hilo de ejecución
  // a parte), pero el método que referencia 'objDA' se ejecuta de manera síncrona.
  // 'IAsyncResult' almacenará información relacionada a ese hilo :
  // IAsyncResult BeginInvoke (, AsyncCallback cb, Object o)
  // En  van los parámetros del típo delegado.
    objIAR = objDA.BeginInvoke ("Hola", objAC, "Hola2");
  // 'objAC' contiene el o los métodos que se quiere que sean asíncronos. '"Hola2"' es
  // un argumento opcional que se le puede enviar a los métodos a ejecutar de forma
  // asíncrona. Es opcional, puede ir tanto '"Hola2"' como 'null'.

  // Cuando se ejecuta el método EndInvoke se muestran los resultados de los métodos
  // llamados, las excepciones que hubieron (si es que hubieron), etc.
  //  EndInvoke (, IASyncResult ar)
    objDA.EndInvoke (objIAR);

  // Si se terminó de ejecutar el hilo o no
    if (objIAR.IsCompleted)
      Console.WriteLine ("Se termino la llamada asíncrona");
    else
      Console.WriteLine ("Aún no termina la llamada asíncrona");

  // Si se terminó de ejecutar el hilo de manera síncrona. Se usa, ya que puede que
  // existan excepciones de las cuales no se informe. Pero esas excepciones se
  // informarán si se utiliza el método EndInvoque.
    if (objIAR.CompletedSynchronously)
      Console.WriteLine ("El hilo se termino de forma síncrona");
  // Si se termino de ejecutar el hilo de manera asíncrona
    else if (objIAR.CompletedSynchronously == false)
      Console.WriteLine ("El hilo se termino de forma asíncrona");

  // Espera a que se presione una tecla
    Console.Read ();
  }

  public static void Método1 (string str)
  {
    Console.WriteLine ("Desde Método1: {0}",str);
  }

  public static void Método2 (IAsyncResult obj)
  {
  // Se obtiene el objeto proporcionado al empezar la ejecución de la operación asíncrona :
  // public object AsyncState [solo lectura]
    Console.WriteLine ("Desde Método2: {0}", obj.AsyncState);
  }
}

La salida:

writkas@linux-xag2:~/Programacion/C#> gmcs -langversion:future Delegados5_Comentado.cs
writkas@linux-xag2:~/Programacion/C#> mono Delegados5_Comentado.exe
Desde Método1: Hola
Desde Método2: Hola2
Se termino la llamada asíncrona
El hilo se termino de forma asíncrona

writkas@linux-xag2:~/Programacion/C#>

Aquí puedes descargar los ejemplos de Delegados en C Sharp que hemos visto hasta ahora.

logo descargar

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp
  5. C Sharp (C#) – Usar delegados – Usar delegados para facilitar el uso de eventos
  6. C Sharp (C#) – Usar delegados – Manejar listas de métodos que referencian los objetos delegados

.

(Parte 6: Manejar listas de métodos que referencian los objetos delegados) Artículo anterior | Artículo siguiente (Parte 7: —)

C Sharp (C#) – Usar Delegados – Parte 6

Manejar listas de métodos que referencian los objetos delegados.

En este artículo veremos:c# logo no oficial del lenguaje de programacion c sharp

  • Como manejar las listas de métodos que referencian los objetos delegados para saber sus métodos y su clase.
  • Combinar 2 objetos delegados (se combinan las listas de métodos que contienen los objetos delegados)
  • Ejecutar todos los métodos que referencia un objeto delegado.

.

El próximo código es un ejemplo puramente teórico que muestra los puntos anteriormente dichos.

// por Writkas, archivo sin derechos reservados.
//
// Delegados4_Comentado.cs : Ejemplo puramente teórico que muestra como manejar las listas
//	de métodos que referencian los objetos delegados para saber sus métodos y su
//	clase, combinar dos objetos delegados y ejecutar todos los métodos que referencia
//	un objeto delegado.
//
// Compilar en Linux con Mono:
//	gmcs Delegados4_Comentado.cs
//
// Ejecutar:
//	mono Delegados4_comentado.exe

using System;
using System.Reflection;

delegate int MiTipoDelegado (int Parámetro);

public class Programa
{
	public static void Main ()
	{
		Console.WriteLine ("Se inicia el programa\n");

		OtraClase objOtraClase = new OtraClase ();

	//	Ya que la palabra clave 'delegate' representa una clase sellada
	//	'System.MulticastDelegate', sus intancias pueden ser inicializadas como cualquier
	//	otra clase.
	//	Entonces ->
	//	MiTipoDelegado miObjDelegado1 = new MiTipoDelegado (objOtraClase.Método1);
	//	Es lo mismo que -->
		MiTipoDelegado miObjDelegado1 = objOtraClase.Método1;

		miObjDelegado1 += objOtraClase.Método2;

		MiTipoDelegado miObjDelegado2 = objOtraClase.Método3;

	//	Este es el objeto delegado que contendra los métodos de 'miObjDelegado1'
	//	y también los de 'miObjDelegado2'. Es importante asignarle un valor nulo (null)
		MiTipoDelegado miObjDelegado3 = null;

	//	Información sobre los objetos delegados tratados gracias a la clase
	//	'TratarDelegados'
		Console.WriteLine ("Mostrar información de 'miObjDelegado1'");
		TratarDelegados.InformaciónObjDelegado (miObjDelegado1);
		Console.WriteLine ("\nMostrar información de 'miObjDelegado2'");
		TratarDelegados.InformaciónObjDelegado (miObjDelegado2);
		Console.WriteLine ("\nMostrar información de 'miObjDelegado3'");
		TratarDelegados.InformaciónObjDelegado (miObjDelegado3);

	//	Combinar los objetos delegados que contienen métodos, para que los contenga
	//	un solo objeto delegado. Y mostrar información de los objetos delegados.
		Console.WriteLine ("\nLuego de combinar los objetos delegados 'miObjDelegado1'");
		Console.WriteLine ("y 'miObjDelegado2' en 'miObjDelegado3'");
		miObjDelegado3 += miObjDelegado1 + miObjDelegado2;
		Console.WriteLine ("\nMostrar información de 'miObjDelegado3'");
		TratarDelegados.InformaciónObjDelegado (miObjDelegado3);

	//	Llamar a todos los métodos de 'miObjDelegado3'
		Console.WriteLine ("\nLlamar a los métodos de 'miObjDelegado3'");
		miObjDelegado3 (5);
	}
}

public class OtraClase
{
	public int Método1 (int a)
	{
		int retorno = a + 10;

		Console.WriteLine ("Soy Método1 y mi argumento es: {0} y retorno: {1}",
		  a, retorno);

		return retorno;
	}

	public int Método2 (int a)
	{
		int retorno = a + 20;

		Console.WriteLine ("Soy Método2 y mi argumento es: {0} y retorno: {1}",
		  a, retorno);

		return retorno;
	}

	public int Método3 (int a)
	{
		int retorno = a + 30;

		Console.WriteLine ("Soy Método3 y mi argumento es: {0} y retorno: {1}",
		  a, retorno);

		return retorno;
	}
}

public class TratarDelegados
{

	public static void InformaciónObjDelegado (Delegate objDel)
	{
		Console.WriteLine ("Información del objeto delegado");

		if (objDel == null) {
			Console.WriteLine ("\tEl objeto delegado no referencia a ningún método");
			return;
		}

		foreach (Delegate d in objDel.GetInvocationList ()) {
			Console.WriteLine ("\tNombre del método: {0}", d.Method);
			Console.WriteLine ("\tNombre de su clase: {0}", d.Target);
		}
	}
}

Ahora compilar y ejecutar –>

writkas@linux-xag2:~> gmcs Delegados4_Comentado.cs
writkas@linux-xag2:~> mono Delegados4_Comentado.exe
Se inicia el programa

Mostrar información de 'miObjDelegado1'
Información del objeto delegado
Nombre del método: Int32 Método1(Int32)
Nombre de su clase: OtraClase
Nombre del método: Int32 Método2(Int32)
Nombre de su clase: OtraClase

Mostrar información de 'miObjDelegado2'
Información del objeto delegado
Nombre del método: Int32 Método3(Int32)
Nombre de su clase: OtraClase

Mostrar información de 'miObjDelegado3'
Información del objeto delegado
El objeto delegado no referencia a ningún método

Luego de combinar los objetos delegados 'miObjDelegado1'
y 'miObjDelegado2' en 'miObjDelegado3'

Mostrar información de 'miObjDelegado3'
Información del objeto delegado
Nombre del método: Int32 Método1(Int32)
Nombre de su clase: OtraClase
Nombre del método: Int32 Método2(Int32)
Nombre de su clase: OtraClase
Nombre del método: Int32 Método3(Int32)
Nombre de su clase: OtraClase

Llamar a los métodos de 'miObjDelegado3'
Soy Método1 y mi argumento es: 5 y retorno: 15
Soy Método2 y mi argumento es: 5 y retorno: 25
Soy Método3 y mi argumento es: 5 y retorno: 35
writkas@linux-xag2:~>

Eso es, espero que les sirva. Si algo no entienden, por favor no duden en escribir un comentario para hacer algunos retoques al artículo

Aquí puedes descargar los ejemplos de los delegados en C Sharp que hemos visto hasta ahora

logo descargar

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp
  5. C Sharp (C#) – Usar delegados – Usar delegados para facilitar el uso de eventos
  6. C Sharp (C#) – Usar delegados – Manejar listas de métodos que referencian los objetos delegados

.

(Parte 5: Usar delegados para facilitar el uso de eventos) Artículo anterior | Artículo siguiente (Parte 7: —)

C Sharp (C#) – Usar Delegados – Parte 5

Usar delegados para facilitar el uso de eventos

En este artículo veremos como usar delegados para facilitar el uso de eventos, es un ejemplo de código. Es la tarea del artículo anterior (C Sharp (C#) – Usar Delegados – Parte 4). Como sugerencia trata de hacer el ejercicio anterior y luego ve este ejemplo de código. Trata de cumplir los objetivos que di en el artículo anterior. En este artículo mostraré el resultado del ejercicio, a lo que mas o menos tenías que llegar. Obviamente no todo escriben código igual, por eso se sugiere que se haga el ejercicio anterior.

Usar delegados para facilitar el uso de eventos.

Choque de coches

Acá va el ejemplo:


// Ejemplo copiado del libro "Pro C Sharp 2010 and the dotNet 4 Platform 5th
// Edition - Andrew Troelsen - Apress" página 405 del libro. Traducido, comentado,
// editado por Writkas
//
// Car--Ejemplo.cs : 	Ejemplo que muestra como usar delegados para facilitar el
//	uso de eventos. Este ejemplo no muestra como usar eventos, lo que trata de
//	mostrar, es un ejemplo en el que podría ser útil el uso de delegados, un
//	ejemplo más o menos real.
//	En resumen el ejemplo trata sobre un auto que va subiendo la velocidad y a
//	traves de notificaciones 'personalizadas' nos avisa del peligro, y estado del
//	auto. Al chocar el auto, suponemos que alguien ejecuta la caja negra del auto
//	y se dencadenan los mensajes (métodos) registrados.
//
// Compilar :			gmcs Car--Ejemplo.cs

using System;

public class Program
{
	public static void Main ()
	{
		Console.WriteLine ("***** Delegados para facilitar eventos *****\n");

	// Crear un objeto de la clase "Car".
		Car c1 = new Car (100, 10);

	// Hay que decirle al objeto "c1" cual es el método a llamar (OnCarEngineEvent)
	// cuando se nos envíe un mensaje o notificación. Debe cumplir con la firma.
		c1.RegisterWithCarEngine (new Car.CarEngineHandler (OnCarEngineEvent));

	// Subir velocidad (este es el punto de partida para luego recibir eventos o
	// mensajes). (el bucle for no tiene llaves por que tiene una sola linea de
	// código y se puede hacer eso)
		Console.WriteLine ("***** subir velocidad *****");
		for (int i = 0; i < 6; i++)
			c1.Accelerate (20);

		Console.ReadLine ();
	}

	// Este es nuestro método personalizado que le enviaremos a el objeto delegado.
	public static void OnCarEngineEvent (string msg)
	{
		Console.WriteLine ("\n****** mensaje desde el objeto c1 *****");
		Console.WriteLine ("=> {0}", msg);
		Console.WriteLine ("************************************\n");
	}
}

public class Car
{
	// 1) Definir un tipo delegado.
	public delegate void CarEngineHandler (string msgForCaller);
	// 2) Definir un objeto delegado miembro de esta clase.
	private CarEngineHandler listOfHandlers;
	// 3) Añadir una función registro para el llamador.
	// Se le envía un objeto delegado (el creado con new, anteriormente) y se copia
	// ese objeto delegado al del objeto delegado de esta clase.
	public void RegisterWithCarEngine (CarEngineHandler methodToCall)
		{ listOfHandlers = methodToCall;}

	// Estados de las variables internas
	public int CurrentSpeed {get; set;} // Velocidad común
	public int MaxSpeed {get; set;} // Velocidad máxima

	// El auto esta vivo?
	private bool carIsDead;

	// Constructores de la clasepe
	public Car () {MaxSpeed = 100; }
	public Car (int maxSp, int currSp)
	{
		CurrentSpeed = currSp;
		MaxSpeed = maxSp;
	}

	public void Accelerate (int delta)
	{
	// ¿Si, este auto esta muerto?, enviar el mensaje de que está muerto.
		if (carIsDead)
		{
	// ¿Si, el objeto delegado 'listOfHandlers' no tiene métodos y es null?
			if (listOfHandlers != null)
				listOfHandlers ("este auto esta muerto...");
		}

		else
		{
			CurrentSpeed += delta;

	// ¿Si, este auto está casi muerto?
			if (10 == (MaxSpeed - CurrentSpeed) && listOfHandlers != null)
				listOfHandlers ("¡cuidado! va a chocar");
	// ¿Si, este auto va a más velocidad del limite o igual velocidad?
			if (CurrentSpeed >= MaxSpeed)
				carIsDead = true;
			else
				Console.WriteLine ("CurrentSpeed = {0}", CurrentSpeed);
		}
	}
}

Compilar el ejemplo y ejecutar para ver el resultado, en Linux u parecidos, si no usas MonoDevelop.

writkas@linux-xag2:/home/writkas/> gmcs Car--Ejemplo.cs
writkas@linux-xag2:/home/writkas/> mono Car--Ejemplo.exe
***** Delegados para facilitar eventos *****

***** subir velocidad *****
CurrentSpeed = 30
CurrentSpeed = 50
CurrentSpeed = 70

****** mensaje desde el objeto c1 *****
=> ¡cuidado! va a chocar
************************************

CurrentSpeed = 90

****** mensaje desde el objeto c1 *****
=> este auto esta muerto...
************************************

writkas@linux-xag2:/home/writkas/>

.

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miebros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp

.

(parte 4: Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp) Artículo anterior | Artículo siguiente (parte 6: Manejar listas de métodos que referencian los objetos delegados)

C Sharp (C#) – Usar Delegados – Parte 4

Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp

En este artículo veremos el como acceder a varios métodos privados y estáticos, de un tipo delegado y objeto delegado, y también repasaremos lo de añadir y quitar métodos en un objeto delegado, y veremos unos atajos que se dieron en la versión 2.0 de el lenguaje C# y por último un ejercicio para entender los delegados en C Sharp . Para estudiar esto hice un pequeño ejemplo de código. Creo que si sigues desde el principio estos mini artículos, podrías entender bien el código.

// por Writkas, archivo sin derechos reservados.
//
// Delegados3.cs : Acceder a varios métodos estáticos y privados de la clase
//	principal (donde esta el main) y otras clases a través de un objeto delegado.
//	También repasamos el añadir y quitar métodos a un objeto delegado con los
//	operadores '=' y '+=' y los atajos que aparecieron en la versión 2.0 de C#.
//
// Compilar en Linux : gmcs Delegados3.cs

using System;

public class EstaClase
{
	public delegate void MiDelegado (int parámetro1, int parámetro2);

	public static void Main ()
	{
		Console.WriteLine ("Se inicia el programa");

	// Se crea una instancia de la clase 'OtraClase'
		OtraClase objOtraClase = new OtraClase ();

		Console.WriteLine ("Se añade al objeto delegado el método estático 'Método1DeOtraClase'");
	// Añadir a 'objDelegado' un método estático de 'OtraClase'
	// Para añadir un primer método a un objeto delegado, se usa el operador '=' .
	// Pero esto vale solo para el primer método a añadir al objeto delegado, el
	// resto de los métodos se añaden con el operador '+=' .
		Console.WriteLine ("Se crea una instancia de la clase 'OtraClase'");
		MiDelegado objDelegado = new MiDelegado (OtraClase.Método1DeOtraClase);

		Console.WriteLine ("Se añade al objeto delegado el método no estático 'Método2DeOtraClase'");
	// Se añade 'Método2DeOtraClase' que no es estático. Ahora usamos el operador
	//'+=' ya que no es el primer método a añadir.
		objDelegado += new MiDelegado (objOtraClase.Método2DeOtraClase);

		Console.WriteLine ("Se añade al objeto delegado el método estático 'Método1DeEstaClase'");
	// Se añade un método estático de esta clase. No hay para que referirse al nombre de esta
		objDelegado += new MiDelegado (Método1DeEstaClase);

		Console.WriteLine ("Se crea una instancia de la clase 'EstaClase'");
	// Crear una instancia de esta clase 'EstaClase'
		EstaClase objEstaClase = new EstaClase ();

		Console.WriteLine ("Se añade al objeto delegado el método no estático 'Método2DeEstaClase'");
	// Se añade un método publico de esta clase
		objDelegado += new MiDelegado (objEstaClase.Método2DeEstaClase);

		Console.WriteLine ("Se llama a objDelegado objDelegado (8, 3);");
	// Llamar a un método estático que se almacena en 'objDelegado'
		objDelegado (8, 3);

	// Ahora, llamamos a los métodos que están relacionados con los métodos de
	// 'objEstaClase' y los de 'objOtraClase'. Se vió que a 'objDelegado' al llamarlo no le
	// importa si los métodos a añadir son estáticos o públicos.

	// Ahora veremos algunos atajos para añadir métodos a un objeto delegado que se añadieron en la
	// versión 2.0 del lenguaje C# . Es importante tener en cuenta estos atajos para usarlos y también
	// leer código de otros programadores.
		objDelegado += objEstaClase.Método2DeEstaClase;
		objDelegado += OtraClase.Método1DeOtraClase;

	// Veamos si funciona
		objDelegado (10, 20);
	}

  public static void Método1DeEstaClase (int parámetro1, int parámetro2)
  {
    Console.WriteLine ("Se a llamado a un método estático 'Método1DeEstaClase' de esta clase");
    Console.WriteLine ("Muestra estos argumentos: {0} y {1}", parámetro1, parámetro2);
  }

  public void Método2DeEstaClase (int parámetro1, int parámetro2)
  {
    Console.WriteLine ("Se a llamado a 'Método2DeOtraClase' de esta clase");
    Console.WriteLine ("Muestra estos argumentos: {0} y {1}", parámetro1, parámetro2);
  }
}

public class OtraClase
{
  public static void Método1DeOtraClase (int parámetro1, int parámetro2)
  {
    Console.WriteLine ("Se a llamado a un método estático 'Método1DeOtraClase' de la clase 'OtraClase'");
    Console.WriteLine ("Muestra estos argumentos: {0} y {1}", parámetro1, parámetro2);
  }

  public void Método2DeOtraClase (int parámetro1, int parámetro2)
  {
    Console.WriteLine ("Se a llamado a 'Método2DeOtraClase' de un objeto de la clase OtraClase");
    Console.WriteLine ("Muestra estos argumentos: {0} y {1}", parámetro1, parámetro2);
  }
}

Ahora veamos la salida, en un terminal (monitor, linea de comandos, etc.) de Linux. Pero creo que es lo mismo que debería salir si lo compilamos compilamos con Visual Estudio. –>

Se inicia el programa
Se añade al objeto delegado el método estático 'Método1DeOtraClase'
Se crea una instancia de la clase 'OtraClase'
Se añade al objeto delegado el método no estático 'Método2DeOtraClase'
Se añade al objeto delegado el método estático 'Método1DeEstaClase'
Se crea una instancia de la clase 'EstaClase'
Se añade al objeto delegado el método no estático 'Método2DeEstaClase'
Se llama a objDelegado objDelegado (8, 3);
Se a llamado a un método estático 'Método1DeOtraClase' de la clase 'OtraClase'
Muestra estos argumentos: 8 y 3
Se a llamado a 'Método2DeOtraClase' de un objeto de la clase OtraClase
Muestra estos argumentos: 8 y 3
Se a llamado a un método estático 'Método1DeEstaClase' de esta clase
Muestra estos argumentos: 8 y 3
Se a llamado a 'Método2DeOtraClase' de esta clase
Muestra estos argumentos: 8 y 3
Se a llamado a un método estático 'Método1DeOtraClase' de la clase 'OtraClase'
Muestra estos argumentos: 10 y 20
Se a llamado a 'Método2DeOtraClase' de un objeto de la clase OtraClase
Muestra estos argumentos: 10 y 20
Se a llamado a un método estático 'Método1DeEstaClase' de esta clase
Muestra estos argumentos: 10 y 20
Se a llamado a 'Método2DeOtraClase' de esta clase
Muestra estos argumentos: 10 y 20
Se a llamado a 'Método2DeOtraClase' de esta clase
Muestra estos argumentos: 10 y 20
Se a llamado a un método estático 'Método1DeOtraClase' de la clase 'OtraClase'
Muestra estos argumentos: 10 y 20

Ahora voy a dejar una tarea, por que pasa que a veces creemos entender de que tratan estos contenidos de programación, pero al llegar a realizar algo se vuelve todo muy complicado.

La tarea también les servirá como ejemplo para entender mejor los delegados. Ya que hemos visto varios ejemplos simples que son muy teóricos pero no expresan el pare que se utilizan los delegados.

Ejercicio para entender los delegados en C#

Choque de coches

Primero, imaginemos un auto que va en una carretera acelerando cada ves más, va aumentando la velocidad. Y que cada vez que aumenta la velocidad el sistema del auto envía un mensaje a la caja negra del auto, para registrar la actividad del auto durante su vida útil. A medida que el auto va acelerando va perdiendo el control y a una cierta velocidad choca. Al final suponemos que alguien revisa el auto y ejecuta la caja negra, y ahí se desencadenan todos los mensajes que registro el auto en su vida.

.

Ahora la parte más técnica.

Objetivos del ejercicio para entender los delegados.

  1. Usar los delegados.
  2. Usar dos clases.
    1. Una para el método Main () y para hacer uso de la clase Car.
    2. Una clase Car, que tendrá todo el mecanismo del auto. Un método para acelerar, un delegado para manejar los métodos o lo que pase dentro del auto (la caja negra).
  3. Hacer que se muestre en el monitor lo principal que pasa en el programa. Que el auto va aumentando la velocidad en x, que el auto esta perdiendo el control a x velocidad, que el auto choca a x velocidad.
  4. Pasar un método personalizado al objeto delegado de la clase Car que contenga la forma en que el mensaje sera mostrado en el monitor (personalizado).

Sugerencias para el programa

En la clase que contiene el Main () tendremos el bucle que hace que el auto aumente la velocidad y el método personalizado, que le queremos pasar a objeto delegado de la clase Car . Nuestro método personalizado deberá contener la forma en que el mensaje será presentado a la supuesta persona que desencadene todos los eventos. Por ejemplo :

*** aumento 10 la velocidad ***

*** aumento 20 la velocidad ***

*** aumento etc la velocidad ***

Esa es la forma en que se mostrarán los eventos.

Queremos crear una clase Car, que contenga los siguientes miembros.

  • public delegate void CarEngineHandler (string msgForCaller); // Se usará para guardar o dejar referenciado a los métodos a asignar.
  • private CarEngineHandler listOfHandlers; // Objeto delegado de la clase Car
  • public void RegisterWithCarEngine (CarEngineHandler methodToCall) // Método que a través de el se le puede enviar un objeto delegado del tipo ‘CarEngineHandler‘ que proporciona esta clase. Para enviar los mensajes que incluye el objeto delegado.
  • public void Accelerate (int delta) // delta es la velocidad que va a aumentar.
  • Las variables internas y otros miembros que manejen todo el mecanismo.

.

Lo principal es cumplir los objetivos del ejercicio, lo demás es solo una sugerencia que es opcional.

Por favor las sugerencias o preguntas son bienvenidas, para hacer unos retoques al artículo por si no se entiendo el ejercicio. Pronto vendrá una solución al ejercicio.

.

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp

.

(parte 3: ¿Cuándo se ocupan los delegados en C Sharp?) Artículo anterior | Artículo siguiente (parte 5: Usar delegados para facilitar el uso de eventos)

[/sourcecode]

C Sharp (C#) – Usar Delegados – Parte 3

¿Cuándo se ocupan los delegados?

Los delegados pueden ser utilizados en distintas ocasiones, también pueden no ser utilizados como en el caso del lenguaje Java. Pero la idea de aprender a usar los delegados es para ser mas eficiente a la hora de programar y ahorrar lineas de código. Al principio usar palabras claves nuevas en un lenguaje de programación moderno puede ser difícil pero cuando ya lo aprendes será mas intuitivo y más eficiente.

Los delegados se pueden usar cuando:

  • Se llama a varios métodos con una sola llamada (Multidifución). A los objetos delegados se les puede asignar métodos y luego llamarlos todos de forma ordenada, con una sola llamada desde el objeto delegado.
  • Se pasan métodos como parámetros. Gracias a usar un tipo delegado como parámetro.
  • La ordenación de un conjunto de elementos. Por ejemplo, ordenar una secuencia de métodos.
  • Se utilice un modelo de diseño de eventos. Los eventos son como las propiedades, son una forma de acceder a los delegados. Dan una respuesta cuando se le asigna y/o quita un método a un evento que representa un objeto delegado (parecido a las propiedades representan a las variables).
  • Se prefiere a la hora de encapsular un método estático. Con llamar a un objeto delegado se puede acceder para llamar a métodos estáticos privados de otra clase (no la clase en la cual esta el autor de la llamada al objeto delegado), sin tener que llamarlos directamente (ya que no se puede llamar a miembros (métodos, variables, propiedades, etc)  privados de forma directa desde otra clase).
  • El autor de la llamada no tiene ninguna necesidad de obtener acceso a otras propiedades, métodos o interfaces de el objeto.
  • Una clase puede necesitar mas de una implementación (realización de una especificación técnica) de métodos.
  • Se desea conseguir una composición sencilla.
  • Para realizar devolución de llamadas asíncronas (en un hilo de ejecución a parte) y finalizar llamadas asíncronas.
  • Cambios en bases de datos. Por ejemplo, a partir de un cambio de ‘x’ tabla se genera una respuesta ‘y’.
  • Asociación de código a la carga y descarga de ensamblados.
  • Cambios en el sistema de archivos. Por ejemplo al borrar ‘x’ archivo se escribe un registro en otro archivo ‘y’, que contiene datos del archivo borrado.
  • Etc.

Si no quedaron muy claras algunas cosas, más adelante se verán. También veremos algunos ejemplos ilustrativos (para aprender a usar los delegados) y ejemplos en un contexto ‘más o menos real’ (ya que son solo ejemplos).

¿Dudas?, ¿sugerencias?, ¿opiniones?, ¿errores?, ¿insultos?

.

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp

.

(parte 2: Añadir y quitar métodos a un objeto delegado) Artículo anterior | Artículo siguiente (parte 4: Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp)

C Sharp (C#) – Usar Delegados – Parte 2

Añadir y quitar métodos a un objeto delegado

En realidad los delegados no son un tema corto, por lo que irán varios mini artículos mas. También, en el ejemplo del mini artículo anterior, se añadió un solo método a un objeto delegado, pero había dicho que también se pueden añadir uno o mas métodos a un objeto delegado y luego en el caso de ser varios métodos se podían ejecutar de forma ordenada a través del objeto delegado (también se puede ejecutar de otras formas pero, ya se vera eso mas adelante). En este mini artículo se verá como añadir y quitar métodos a un objeto delegado y ejecutarlos de forma ordenada.

Normalmente cuando se crea un objeto delegado, en la misma linea (o sentencia) se incluye el primer método que le asignamos. Pero ¿como añadimos más métodos a un objeto delegado? en el caso de que se quera añadir o quitar métodos a un objeto delegado, se usa los operadores ‘+=’ para añadir y ‘-=’ para quitar métodos. Estos son operadores sobrecargados para que el uso de los objetos delegados sean mas intuitivos.

Ejemplo de como añadir y quitar métodos a un objeto delegado

// por Writkas, archivo sin derechos reservados.
// Delegados2.cs : Añadir y quitar métodos a un objeto delegado

using System;

public class Programa
{
 // Se crea y define un tipo delegado, se puede definir también dentro de una clase.
 // Se define el tipo delegado, tipo de retorno, numero de parámetros y tipos de parámetros. Los
 // métodos a asignar al objeto delegado deben cumplir con esta definición, o si no dará error.
 public delegate void TipoDelegado ();

 public static void Main ()
 {
   Console.WriteLine ("Se inicia el programa");

 // Se crea una objeto de la clase Programa
   Programa objPrograma = new Programa ();

 // Se crea un objeto de el tipo delegado y se le añade un método. No importá si el método es de
 // un objeto de la propia clase
   TipoDelegado objDelegado = new TipoDelegado (objPrograma.Método1);

 // Se añade al objeto delegado un método, ahora el objeto delegado tendrá 2 métodos añadidos.
 // Al añadir un primer método a un delegado se puede usar el operador de asignación '=' pero
 // si quisiéramos añadir otro método se tiene que usar el operador '+=' , como lo siguiente.
   objDelegado += new TipoDelegado (objPrograma.Método2);

   Console.WriteLine ("Se llamará al objeto delegado con los métodos ya asignados");
   objDelegado ();

   Console.WriteLine ("Se llamará al objeto delegado después de quitar Método2");
 // Quitar el método 'Método2' y luego llamar al objeto delegado
   objDelegado -= new TipoDelegado (objPrograma.Método2);
   objDelegado ();

 // Se puede añadir el mismo método mas de una ves
   Console.WriteLine ("Se añade -de nuevo- Método1");
   objDelegado += new TipoDelegado (objPrograma.Método1);
   objDelegado ();
 }

 // Observa que los métodos cumplen con la definición del tipo delegado
 public void Método1 ()
 {
   Console.WriteLine ("Soy Método1");
 }

 public void Método2 ()
 {
   Console.WriteLine ("Soy Método2");
 }
}

El resultado es (en Linux usando Mono y el Terminal) ->

writkas@linux-e1ht:~/proyectos> mcs Delegados2.cs
writkas@linux-e1ht:~/proyectos> mono Delegados2.exe
Se inicia el programa
Se llamará al objeto delegado con los métodos ya asignados
Soy Método1
Soy Método2
Se llamará al objeto delegado después de quitar Método2
Soy Método1
Se añade -de nuevo- Método1
Soy Método1
Soy Método1
writkas@linux-e1ht:~/proyectos>

Enfatizo

  • Un tipo delegado se puede definir dentro de una clase, fuera de una clase, dentro de un namespace o fuera de un namespace.
  • Al inicializar un objeto delegado, se le puede asignar un método usando el operador ‘=’ , pero para asignar o quitar otros métodos al objeto delegado se tiene que usar los operadores ‘+=’ y ‘-=’.
  • Para añadir y quitar un método a un objeto delegado se utilizan los operadores ‘+=’ para añadir y ‘-=’ para quitar un método.
  • Al llamar al objeto delegado se ejecutan los métodos que almacena de forma ordenada, salen al mismo orden de como se añadieron. Osea, si se añade Método1 y luego Método2, al llamar al objeto delegado saldrán Método1 primero y luego Método2.
  • Un mismo método se puede añadir a un objeto delegado más de una ves.

Ya irán mas mini artículos sobre el tema sobre usar delegados en C Sharp. Puede que gente que sabe sobre este tema diga que estoy ignorando muchas cosas sobre este tema los delegados, pero eso estoy haciendo, para ir de forma ordenada y que se entienda mejor el tema.

.

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp
  5. C Sharp (C#) – Usar delegados – Usar delegados para facilitar el uso de eventos

.

(Parte 1: Añadir y quitar métodos a un objeto delegado) Artículo anterior | Artículo siguiente (Parte 3: ¿Cuándo se usan los delegados?)

C Sharp (C#) – Usar delegados – Parte 1

Ejemplo mínimo sobre delegadosLogo no oficial de C#

C Sharp es un lenguaje de programación para los proyectos Mono y .Net . Este lenguaje de programación, a diferencia de otros, trae bastantes palabras claves (keywords) para facilitar la vida de los programadores, la palabra clave delegate es una de ellas. El equivalente de los delegados en el lenguaje C/C++ sería un puntero a función (callback). Pero por la complejidad de los punteros a función de el lenguaje C/C++ muchas veces  se producen bugs y errores en tiempo de ejecución. C# soluciona el problema incluyendo los delegados. Para crear un delegado se usa la palabra clave delegate, la razón para crear esta palabra clave es por que aporta más seguridad. Considero bueno que los lenguajes de programación tengan muchas palabras claves, aunque cuesta mas aprenderlas ya que son más temas de estudio. Es una inversión para ser más rápido e eficiente a la hora de crear una aplicación. 

¿Qué es un delegado en C Sharp?

Antes, creo importante hacer una diferenciación entre lo que es un objeto delegado y un tipo delegado, por que son distintos y se hablara de ellos en todos los mini artículos.

  • Un tipo delegado es el que se define con la palabra clave delegate
  • En cambió un objeto delegado es una instancia de ese tipo delegado.

Esquema de un tipo delegado a un objeto delegado

Un delegado es un tipo en el cual hay que definir (o firma) que debe cumplir el o los métodos a añadir a su objeto delegado. El objeto delegado puede solicitar llamar a uno o más de el o los métodos añadidos a la vez.

,

Ejemplo sobre delegado en C Sharp

// por Writkas, archivo sin derechos reservados.
// Delegados1.cs : Ejemplo mínimo sobre delegados

using System;

// Un delegado puede estar dentro de una clase, fuera de una clase, dentro de
// un namespace o fuera de un namespace.

// Se crea y define el -tipo- delegado, en la definición (o firma) de un tipo delegado
// se consideran: el tipo de retorno, número de parámetros y el tipo de los parámetros,
// con estas características deben cumplir los métodos que luego se asignarán.
// Para crear un tipo delegado se usa la palabra clave delegate
public delegate int MiDelegado (int parámetro);  // Es muy similar a declarar un método

public class Programa
{
  public static void Main ()
  {
    Console.WriteLine ("Se inicia el programa");

  // Se crea un objeto de la clase 'OtraClase'
    OtraClase objOtraClase = new OtraClase ();

  // Se crea un objeto delegado y se le asigna un método, en este ejemplo le
  // asignamos solo un método, pero se le pueden asignar más.
  // Crear un objeto delegado es muy similar a crear un objeto con una clase, la
  // diferencia es que le asignamos un método.
  // El método no se llama usando '()' solo se le asigna al objeto delegado, por eso
  // no se usan los '()'
    MiDelegado objDelegado = new MiDelegado (objOtraClase.Método1);

  // Se crea una variable de tipo int y se le asigna el valor de retorno
  // del objeto delegado, que es el mismo retorno de el método anteriormente asignado
    int retorno = objDelegado (5); // Se hace la llamada de la misma forma que un método

  // Muestra el valor de retorno
    Console.WriteLine ("El valor devuelto es {0}", retorno);
  }
}

public class OtraClase
{
  // Este método cumple con el prototipo de el delegado al cual se lo asignamos
  public int Método1 (int a)
  {
    Console.WriteLine ("Soy Método1 y mi argumento es: {0}", a);
    return a + 10;
  }
}

.
Compilar y ejecutar el programa

writkas@linux-xag2:/home/writkas/> gmcs Delegados1_Comentado.cs
writkas@linux-xag2:/home/writkas/> mono Delegados1_Comentado.exe
Se inicia el programa
Soy Método1 y mi argumento es: 5
El valor devuelto es 15
writkas@linux-xag2:/home/writkas/>

Recuerda

  • Un tipo delegado es el cual se define con la palabra clave delegate y un objeto delegado es el objeto de el tipo que se definió anteriormente. También cuando se habla de un delegado es lo mismo que hablar de un tipo delegado.
  • Un tipo delegado se define de forma muy parecida a definir un método de una clase. La diferencia es que se usa la palabra clave delegate y otras cosas.
  • El tipo delegado crea un objeto delegado de la misma forma que una clase, un objeto delegado se puede inicializar asignando el nombre de el método que se quere añadir,  solo el nombre sin usar ‘()’ .
  • Se llama a un objeto delegado de la misma forma que a un método, osea se toma en cuenta el tipo de el valor de retorno, el número de parámetros y el tipo de el o los parámetros.

.

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

| Artículo siguiente (Parte 2: Añadir y quitar métodos a un objeto delegado)

// por Writkas, archivo sin derechos reservados. // Delegados1.cs : Ejemplo mínimo sobre delegadosusing System;// Un delegado puede estar dentro de una clase, fuera de una clase, dentro de // un namespace o fuera de un namespace.  // Se crea y define el -tipo- delegado, en la definición (o firma) de un tipo delegado // se consideran: el tipo de retorno, número de parámetros y el tipo de los parámetros, // con estas carácterísticas deben cumplir los métodos que luego se asignarán. // Para crear un delegado se usa la palabra clave delegate public delegate int MiDelegado (int parámetro);  // Es muy similar a declarar un método public class Programa { public static void Main () { Console.WriteLine (“Se inicia el programa”); // Se crea un objeto de la clase ‘OtraClase’ OtraClase objOtraClase = new OtraClase (); // Se crea un objeto delegado y se le asigna un método, en este ejemplo le // asignamos solo un método, pero se le pueden asignar más. // Crear un objeto delegado es muy similar a crear un objeto con una clase, la // diferencia es que le asinamos un método. // El método no se llama usando ‘()’ solo se le asigna al objeto delegado, por eso // no se usan los ‘()’ MiDelegado objDelegado = new MiDelegado (objOtraClase.Función1); // Se crea una variable de tipo int y se le asigna el valor de retorno // del objeto delegado, que es el mismo retorno de el método anteriormente asignado int retorno = objDelegado (5); // Se hace la llamada de la misma forma que un método // Muestra el valor de retorno Console.WriteLine (“El valor devuelto es {0}”, retorno); } } public class OtraClase { // Este método cumple con el prototípo de el delegado al cual se lo asignamos public int Función1 (int a) { Console.WriteLine (“Soy Función1 y mi argumento es: {0}”, a); return a + 10; } }