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]