InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
También puedes ver ...
SubVersion y Visual Studio
Encriptación con AES Rijndael - Ejemplo
TripleDES - Un ejemplo practico en C#
Insertar una marca de agua en documentos PDF
Serialización: XmlSerializer y BinaryFormater
Handler para manipular imagenes
Conversiones de tipos personalizadas (VB y C#)
Compresión por gzip y deflate
La página Web que está abriendo contiene tanto elementos seguros como no seguros.
Cómo insertar un fichero .xml en un campo de tipo XML de SQL server 2005 o 2008


  Delegados en C#.

  Introducción.

  Uno de los temas que más suelen confundir a los nuevos programadores de la plataforma .NET, al menos a mí, son los delegados. Para los programadores de C++ el concepto es muy similar al de los punteros a funciones,   los programadores de JavaScript tienen una funcionalidad parecida a través de objetos Function (que rara vez se utilizan), pero para el resto es totalmente nuevo.

   Lo primero que vamos a hacer es intenter definir que son los delegados. Una buena definición seria: 

   Los delegados son un tipo que representa a una función con una determinada declaración.

   Vamos a analizar esta definición poco a poco, ya que dice mucho en muy pocas palabras ...

  • Los delegados son un TIPO.
  • Los delegados representan a una función.
  • La función debe tener una determinada declaración.

   Si un delegado es un tipo, entonces puedo crear variables de ese tipo. También hemos dicho que un delegado representa a una función, por lo que una variable creada de un tipo delegado es la representación de una determinada función. Por úlitmo hemos dicho que esta función debe tener una determinada declaración.

  Un ejemplo sencillo.

   Veamos un ejemplo que es como mejor se ven las cosas:


using
System;
namespace Devjoker.Ejemplos 
{
   delegate int myDelegate(int arg) ;
}

   En este caso hemos declarado un tipo delegado, al que hemos llamado myDelegate que representa a una función que devuelve un entero y que recibe como argumento también un entero. Como es un tipo no es necesario definirlo dentro de una clase. Como resultado vamos a poder declarar variables del tipo myDelegate.

   La siguiente pregunta seria,¿Como declaro variables de tipo myDelegate? ¿y como asigno "valores" a esa variable?. Los delegados se declaran como cualquier otro objeto en .NET, recordemos que todo en .NET son objetos y los delegados no son una excepción. Para asignar un delegado, no debemos asignar un "valor", sino un método, normalmente una funcion. El método al que asignemos el delegado no puede ser una función cualquiera, debe cumplir con la declaración del delegado. La forma de asignarlo es a través del constructor del delegado, pasando como argumento la función.

   A continuacion mostramos dos posibles funciones que cumplen con la declaración del delegado:


private
int delegateFunction1(int a)
{
      Console.WriteLine("Ejecutando ... delegateFuntion1");
      return ++a;
}
private int delegateFunction2(int a)
{
      Console.WriteLine("Ejecutando ... delegateFuntion2");
      return a;
}

    Como podemos ver tanto delegateFuntion1 como delegateFunction2 son functiones que devuelven un tipo int y reciben como parametro un int, que es la forma en la que hemos declarado el delegado.

   La declaración de una variable con el tipo delegado, es la siguiente, como cualquier otra variable en C#:


myDelegate
variableDelegado;

   Ahora vamos a ver como asignar un delegado. Hemos dicho que para asignar un delegado necesitamos utilizar el constructor del mismo. En el siguiente ejemplo vamos a ver un pequeño programa completo que declara y ejecuta un delegado:

using System;
namespace Devjoker.Ejemplos 
{
   delegate int myDelegate(int arg) ;
  
   class MainClass
   {
       public static void Main(string[] args)
      {
            MainClass instancia = new MainClass();           
            myDelegate variableDelegado;
            variableDelegado =
            new myDelegate(instancia.delegateFunction1);
            int a = variableDelegado(5);
            System.Console.WriteLine("El resultado obtenido es ... {0}",a);
      }
     
      private int delegateFunction1(int a)
      {
            Console.WriteLine("Ejecutando ... delegateFuntion1");
            return ++a;
      }

      private int delegateFunction2(int a)
      {
            Console.WriteLine("Ejecutando ... delegateFuntion2");
            return a;
      }
   }
}

   En este ejemplo declaramos una variable variableDelegado y la asignamos a la función delegateFunction1. Debido a que el método Main es estático, pero delegateFunction1 no lo es, necesitamos una instancia de la clase MainClass para referiros a la función de forma concreta. Por úlitmo ejecutamos nuestra variable (con un parámetro fijo 5) y mostramos el resultado en pantalla.  

   El programa genera una salida similar a la siguiente:


Ejecutando ... delegateFuntion1
El resultado obtenido es ... 6
Presione una tecla para continuar . . .

   Seguro que alguno de vosotros está pensando en que esto mismo podría hacerse invocando a la funcion sin más, y no andar con tanto lio. Por supesto, pero este es un ejemplo muy sencillo y no pretende mostrar los casos complicados, recordemos que queremos aprender que son y para que sirven los delegados.

   Un caso más complejo podría ser el siguiente, Imaginemos un control creado dinamicamente por el programa, sobre el que queramos programar su click ... La forma de hacerlo es con delegados.

   La función a la que asignamos el delegado no debe pertenecer a una clase en concreto, ni siquiera a un assemblie en particular, solo debe cumplir la declaración del delegado.

   Vamos ahora a ver un ejemplo algo más practico.

  Un ejemplo practico.

   El siguiente ejemplo, sin pretender entrar en mucha complejidad, es un sencillo programa que realiza su log de proceso bien por pantalla o en un fichero.

   El programa tiene tres clases:

  • MainClass, que es la clase que contiene el método main.

  • ProgramClass, que es la clase que contiene el programa principal.

  • FormasLog, que es la clase que contiene las diferentes formas para realizar el log del proceso.

   El programa tiene además un delegado, que vamos a utilizar para realizar el log del proceso.Tienbe la siguiente forma:


delegate void logDelegate(string arg);

   Veamos cada una de estas clases. Empezaremos con la clase FormasLog, que tiene dos métodos (que coinciden con la declaración del delegado), ConsoleLog y FileLog. ConsoleLog muestra un mensaje en pantalla y FileLog, escribe el mensaje en un fichero (ubicado en la misma ruta que el assemblie).

   El codigo de la clase es el siguiente:

class FormasLog
      {
            private static StreamWriter fw;
            public static void ConsoleLog(string texto)
            {
                  System.Console.WriteLine(texto);
            }
            public static void FileLog(string texto)
            {
                  try
                  {
                        bool append = true;
                        if (fw == null)
                        {
                              append = false;
                        }
                        fw =
                        new StreamWriter( "ficherolog.log",append);
                        fw.WriteLine(texto);
                        fw.Close();
                  }
                  catch (IOException e)
                  {                      
                        FormasLog.ConsoleLog(e.Message);
                  }
            }
      }

 

   La clase ProgramClass tiene los siguientes métodos y miembros:

  • logFunction, que es un miembro de tipo logDelegate y es la función encargada de realizar el log
  • Run, que es el método principal de la clase, unicamente comprueba que logFunction está asignada e itera 100 veces llamando al método Log.
  • SetLogMethod, este método es el más importante de todos, ya que recibe un parámetro de tipo logDelegate y lo asigna a logFunction para que pueda hacer su trabajo de forma correcta.
  • Log, este método ejecuta logFunction.

   El código completo de la clase se muestra a continuacion:


class
ProgramClass
      {
            logDelegate logFunction;
            public void Run()
            {
                  if (logFunction == null)
                  {
                  logFunction =
                  new logDelegate(FormasLog.ConsoleLog);
                  }
                  int i = 0;
                  do
                  {
                  logFunction(
                  "Este es el log! en la iteracion " + i.ToString());
                  }
                  while (i++<100);
            }
            public void SetLogMethod(logDelegate metodo)
            {
                  logFunction = metodo;
            }
          
            private void Log(string texto)
            {
                  logFunction(texto);
            }
      }

 

   Por último tenemos la clase MainClass que es la clase que contiene el método Main en el que se inicia la ejecución del programa.

   El método Main crea una instancia de la clase ProgramClass a la que llamamos "programa", y solicita al usuario que especifique una forma para realizar el log. Dependiendo de la selección del usuario llama al método SetLogMethod  del objeto "programa" pasandole una nueva variable de tipo logDelegate construida con las funciones que proporciona la clase FormasLog.

   El código de la clase es:

class MainClass
      {
            public static void Main(string[] args)
            {                
                  ProgramClass programa = new ProgramClass ();
                  string valor = "";
                  do
                  {
                  Console.WriteLine("?Que forma de log quiere?");
                  Console.WriteLine("1->Consola 2->Fichero");
                  valor = System.Console.ReadLine();
                  }
                  while (valor != "1" && valor!= "2" );                                 
                 
                  if (valor == "1")
                  {
                        programa.SetLogMethod(
                        new logDelegate(FormasLog.ConsoleLog));
                  }
                  else if (valor =="2")
                  {
                        programa.SetLogMethod(
                        new logDelegate(FormasLog.FileLog ));
                  }
                  programa.Run ( );
            }                        
      }

   La gran ventaja de esta forma de trabajar es que podemos cambiar la forma en la que el programa realiza el log desde el exterior del programa sin ningún tipo de esfuerzo. Imaginemos que las clase FormasLog  y ProgramClass constituyen un componente de software compilado en un assemblie miComponente.dll. Por otro lado, la clase MainClass pertenece a otro assemblie completamente diferente, otroAssemblie.dll. En este escenario es posible que las formas de log que hemos predeterminado no sean suficientes como para cubrir las necesidades del programa, por ejemplo el log debe guardarse en una base de datos. Podríamos escribir una nueva funcion y decirle al componente que la utilice, solo tendríamos que llamar al metodo SetLogMethod.

   El código completo del programa se muestra a continuación:


namespace Devjoker.Ejemplos
{
      delegate void logDelegate(string arg) ;
     
      class MainClass
      {
            public static void Main(string[] args)
            {                
                  ProgramClass programa = new ProgramClass ();
                  string valor = "";
                  do
                  {
                  Console.WriteLine("¿Que forma de log quiere?");
                  Console.WriteLine("1->Consola 2->Fichero");
                  valor = System.Console.ReadLine();
                  }
                  while (valor != "1" && valor!= "2" );                                 
                  if (valor == "1")
                  {
                        programa.SetLogMethod(
                        new logDelegate(FormasLog.ConsoleLog));
                  }
                  else if (valor =="2")
                  {
                        programa.SetLogMethod(
                        new logDelegate(FormasLog.FileLog ));
                  }
                  programa.Run ( );
            }
      }
      class ProgramClass
      {
            logDelegate logFunction;
            public void Run()
            {
                  if (logFunction == null)
                  {
                  logFunction =
                  new logDelegate(FormasLog.ConsoleLog);
                  }
                 
                  int i = 0;
                  do
                  {
                  logFunction(
                  "Este es el log! en la iteracion " + i.ToString());
                  }
                  while (i++<100);
            }
            public void SetLogMethod(logDelegate metodo)
            {
                  logFunction = metodo;
            }
            private void Log(string texto)
            {
                  logFunction(texto);
            }                       
      }
      class FormasLog
      {
            private static StreamWriter fw;
            public static void ConsoleLog(string texto)
            {
                  System.Console.WriteLine(texto);
            }
            public static void FileLog(string texto)
            {
                  try
                  {
                        bool append = true;
                        if (fw == null)
                        {
                              append = false;
                        }
                        fw = new StreamWriter( "ficherolog.log",append);
                        fw.WriteLine(texto);
                        fw.Close();
                  }
                  catch (IOException e)
                  {                      
                        FormasLog.ConsoleLog(e.Message);
                  }
            }
      }
 }

   Como hemos podido ver los delegados son una potentisima herramienta que ofrece, no solo C# sino la plataforma .NET.

   Espero que este articulo os haya servido de ayuda para entender un poco mejor los delegados, y si teneis alguna duda al respecto no dudeis en exponerla en los foros.

   Saludos y hasta la proxima, Devjoker

 


 Versión para imprimir  Foros de consulta

 
Delegados por Sergio
Respuesta recibida el [24/07/2007 11:13:01]
Muy buena exlicación. Muchas gracias.

 
Delegados por Fern@ndo
Respuesta recibida el [31/10/2007 03:25:29]
Excelente

 
Muy bueno, estaba buscando alg... por Daniel
Respuesta recibida el [23/01/2008 06:07:06]
Muy bueno, estaba buscando algo para entenderlos y me cerraron muchas cosas, gracias

 
Cojonuda explicación por tonio
Respuesta recibida el [14/02/2008 10:32:32]
Pues solo decir que es una expliación barbara, fácil...
Gracias

 
Clarisimo por Cesar.NET
Respuesta recibida el [23/04/2008 02:12:23]
mas claro ni el agua 
gracias

 
Muy bien explicado por Nicolas
Respuesta recibida el [11/05/2008 02:12:54]
Muchas gracias che! 

 
Ahora conozco mi ignorancia por JPMarichal
Respuesta recibida el [17/05/2008 11:42:03]
Gracias, me has iluminado excelentemente bien el panorama. Muy buena explicación.

 
Muy bueno ti tuto por Jher Von Arbanel
Respuesta recibida el [16/06/2008 10:47:17]
Esta de la puta madre tu explicacion ni yo pude hacerlo mejor

 
MUUUUUUUUUY BUENO por Sergio
Respuesta recibida el [24/06/2008 10:47:58]
Buena explicación, ahora entiendo un poco más este asunto de los delegados.

 
no entiendo nada... por Anónimo
Respuesta recibida el [03/07/2008 09:30:13]
no entiendo nada

 
Mil Gracias por Eudorax
Respuesta recibida el [18/08/2008 06:12:31]
Buenisimo, sin rodeos, realmente a lo que está enfocado el ejemplo, gracias al autor.

 
Bien, pero... por Rubén
Respuesta recibida el [13/02/2009 01:40:10]
Esta muy bien la explicación, pero no solo basta entenderlo, hay que practicar para comprenderlo por completo.

 
Por fin pude implementar un delegado por Francisco
Respuesta recibida el [17/03/2009 11:35:42]
Muchas gracias por tu colaboracion. por fin pude entender como se implementa un delegado.

saludos

 
Muy claro, estoy viendo Prism ... por Cristian
Respuesta recibida el [19/03/2009 11:55:23]
Muy claro, estoy viendo Prism y la verdad están por todos lados.
Saludos.
Cristian

 
sigo teniendo la misma duda por JoseCho
Respuesta recibida el [26/03/2009 10:17:26]

Pero entonces, si cuando utilizas un delegado hace lo mismo que cuando invocas al método, ¿para qué sirve el delegado?¿para qué se usa?¿No es más fácil llamar simplemente al método?

Gracias.

 
Para JoseCho por Devjoker
Respuesta recibida el [26/03/2009 10:29:35]
No es lo mismo!
El delegado puede ser cualquier método con esa firma (incluso puede que no exista el método!) y se puede asignar.
Por ejemplo el click de un boton (realmente cualquier evento) no sabe que método tiene que invocar hasta que el programador escribe la función.
En pseudo-codigo seria algo así:
Si la variable delegado tiene valor entonces ejecuto la funcion (Sea la que sea siempre que cumpla la firma)

 
Muchas gracias, tenia una idea... por Sebastián García
Respuesta recibida el [27/12/2009 04:26:24]
Muchas gracias, tenia una idea vaga de que en c# se podian hacer esas cosas pero no sabia como. La explicacion es muy fluida y facil de entender. Ahora estoy usando delegados, para definir interpolaciones en mis videojuegos.

 
Duda por Arthur
Respuesta recibida el [16/02/2010 12:40:47]
logFunction("Este es el log! en la iteracion " + i.ToString());

En esta linea no entiendo por que mandas a llamar al metodo LogFuncion en vez del metodo Log propio de la clase.


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



 Versión para imprimir

Delegados en C#
Autor: Pedro Herrarte Sánchez
Visitas: 10011 Fecha de publicación: 16/11/2005
Pedro Herrarte, es consultor independiente, ofreciendo servicios de consultoría, análisis, desarrollo y formación.

Posee mas de diez años de experiencia trabajando para las principales empresas de España.

Es especialista en tecnologías .NET, entornos Web, bases de datos (SQL Server y ORACLE) e integración de sistemas.

Es experto en desarrollo (C#, ASP.NET, VB.Net, T-SQL, PL/SQL, , ASP, CGI , C, Pro*C, Java, Essbase, Vignette, PowerBuilder y Visual Basic ...) y bases de datos (SQL Server y ORACLE).

Es fundador, diseñador y programador de www.devjoker.com.




Visitas: 87 | Comentarios: 2 | Archivo: Articulos
02/02/2010 iPad vs Telesketch
Visitas: 792 | Comentarios: 2 | Archivo: Articulos
Categorias: Humor
Visitas: 742 | Comentarios: 3 | Archivo: Articulos
Visitas: 3137 | Comentarios: 2 | Archivo: Articulos
Categorias: C#
Visitas: 14494 | Comentarios: 7 | Archivo: Articulos
Categorias: C#|Seguridad
Visitas: 1474 | Comentarios: 3 | Archivo: Articulos
Visitas: 691 | Comentarios: 2 | Archivo: Articulos
Visitas: 368 | Comentarios: 0 | Archivo: Articulos
Visitas: 2007 | Comentarios: 2 | Archivo: Articulos
Categorias: C#

Útimos temas recibidos en los foros ...
quiero saber en que entidad estoy afiliada a cesantias y pensiones por adriana ... [WIN 98/NT/2000/XP] 23 28/11/2009
Certificado de afiliacion Pensiones y Cesantias por VIVIANA ... [Actualidad] 1 10/03/2010
certificado de pensiones del bbva horizonte por danger ... [Actualidad] 122 12/01/2010
CERTIFICADO por LIZETH ... [Actualidad] 0 11/03/2010
certificado de afiliación de pensiones y cesantias por secre ... [Actualidad] 111 28/01/2010
Solicitud certificado de afiliaciones a pensiones y cesantias proteccion por hz ... [Actualidad] 54 10/02/2010
certificado pensiones horizonte por angela patricia rodriguez ... [Actualidad] 135 26/01/2010
pensiones por eduard ... [Visual Basic 6.0] 0 11/03/2010
Manual Visual Studio.NET por Shiko ... [Visual Basic .NET] 41 26/10/2006
cap de setmana genial por ramón ... [Java] 0 11/03/2010
cetificado de pension por RICARDDO RAFAEL SOLANO ORZCO ... [Actualidad] 0 11/03/2010
solicitud de aifiliacion a porvernir por julios ... [Actualidad] 2 11/03/2010

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
22/10/2005 Indices    forma parte de...Tutorial SQL
22/10/2005 Tablas    forma parte de...Tutorial SQL
07/11/2006 Enumeraciones    forma parte de...Tutorial C#
22/10/2005 Actualización de datos. UPDATE    forma parte de...Tutorial SQL
01/01/2006 Borrado de datos. DELETE    forma parte de...Tutorial SQL
28/06/2006 Propagacion de excepciones en PL/SQL    forma parte de...Tutorial PL/SQL
28/06/2006 Procedimientos almacenados en PL/SQL    forma parte de...Tutorial PL/SQL
22/10/2005 Insertar datos. INSERT    forma parte de...Tutorial SQL
05/12/2006 Manipulación de punteros    forma parte de...Tutorial C#
24/07/2006 SQL Dinamico    forma parte de...Tutorial PL/SQL

 

Encuesta
¿A que perfil te adaptas mejor?




[Ver] [Votar]