Métodos Anónimos y Predicados en C# – Parte I

Los métodos anónimos fueron una novedad en la versión de C# .NET 2.0. Están pensados para simplificar la definición de manejadores de eventos cuando las tareas a realizar son simples.  

Pues usted se preguntará ¿y que és un método anónimo?  Un método anónimo es justamente eso, aquel método que no tiene un nombre específico. Y ahora usted se preguntará ¿y cómo invoco los método anónimos?, pues buena pregunta, la respuesta es usando Delegados.

Los delegados son una característica muy interesante del NetFramework que nos permiten pasar métodos como parámetros de otros métodos, extraño, puede ser, pero es menos complicado de lo que parece. En el NetFramework 2.0 nos podemos encontrar con los delegados por todas partes, en diferentes formas, como delegados, como predicados, como acciones.

¿Qué es un delegado?

Como dije antes un delegado nos permite pasar un método como parámetro de otro método, ok, sabemos cómo hacer para pasar tipos de datos como parámetros, simplemente declaramos en tipo y el nombre, detengámonos un momento, si yo quisiera indicar que en cierto lugar espero un método para utilizarlo qué cosas tengo que establecer. La respuesta es clara, el tipo de retorno del método y los parámetros que acepta, bueno, esto es justamente un delegado, una firma que nos permite establecer cómo deberá ser el método que esperamos.

Ejemplo :

Vamos a ver la declaración de un delegado para utlizarlo en un método nuestro como parámetro
.

     public delegate void MiDelegado(string mensaje);

Es muy claro que si quitamos la palabra delegate de esta declaración es idéntica a una declaración de un método cualquiera. Ahora vamos a crear un método que espere un delegado del tipo MiDelegado para invocar el método dentro.

 

     public void TestDelegado(MiDelegado delegado)

   {

          delegado("\r\n Vamos a MJ \r\n http://jonnathandeveloper2008.spaces.live.com/ \r\n Jonnathan!!!");

    }

Ok, este método va a tomar como parámetro un delegado del tipo MiDelegado (o sea un método que devuelva void y tome un string como parámetro) y luego lo va a invocar. Veamos la llamada al método.
Primero creamos el método que utlizaremos como parámetro del tipo MiDelegado.

    public void MetodoDelegado(string mensaje)

   {

      Console.WriteLine(mensaje);

    }

Sencillo, el método recibe un string lo escribe en la consola y no devuelve nada. Ahora vamos a ver cómo se invoca.

Más sencillo aún, lo corremos y vemos que funciona.

Ejemplo Delegados

Vemos declaramos el delegado y le pasamos como parámetro el método que cumple con el delegado. esto lo podríamos haber resumido así

       TestDelegado(new MiDelegado(delegate(string message)

       {

           Console.WriteLine(message);

       }));

Lo que hacemos aquí es definir en la misma línea el delegado y la implementación, esto es lo que se conoce como método anónimo. Es un método anónimo justamente porque no tiene nombre, si bien a simple vista puede parecer que el código se pone confuso, en muchas ocasiones es más práctico utilizar un método anónimo.

El detalle es que siempre hemos estado acostumbrados a nombrar las métodos, tanto aquellos que devuelven valores nulos o los que devuelven un cierto valor para su posterior uso.

Lo importante es que los métodos anónimos,  reduce la sobrecarga de codificación al crear instancias de delegados sin tener que crear un método independiente. Un método anónimo es declarado con la palabra clave delegate seguido de una lista de parámetros. Las líneas de código para el método están dentro del par de llaves {}. Todo esto debe ser referenciado por un tipo delegate que tenga la misma firma que el método anónimo, es así que, la invocación de los métodos anónimos se realiza usando esta referencia

Imaginemos que queremos asociar una única línea de código (o dos) como acción a realizar cuando se produzca un evento. Por ejemplo, que cuando se pulse un botón se muestre un mensaje de saludo. Lo que debíamos hacer hasta ahora era declarar una función del tipo adecuado y asociarla con un nuevo delegado al evento. Por ejemplo:

      private void button1_Click(object sender, System.EventArgs e)

      {

          MessageBox.Show("Hola");

      }

      button1.Click += new System.EventHandler(button1_Click);

Esto hace que al pulsar el botón se vea el saludo "Hola". Sin embargo es un poco engorroso para tan poca acción tener que crear una función como esta. Para evitarlo se han incluido en C# 2.0 los métodos anónimos.

Un método anónimo nos permite definir una función de manera implícita, sin necesidad de declararla. En el ejemplo anterior un método anónimo sustitutivo sería el siguiente:

     button1.Click += delegate { MessageBox.Show("Hola"); };

La única diferencia es que ahora no nos hace falta definir una función, lo hace automáticamente por nosotros el compilador a la hora de crear el ejecutable.

Dependiendo del tipo de evento que estemos asignando el compilador ya deriva de forma automática los parámetros que necesita el método anónimo así como el tipo de delegado que se debe crear (en este caso System.EventHandler).

En algunos tipos de eventos, como la pulsación del ratón y otros, necesitaremos acceder a los parámetros de éste para conocer cierta información. En este caso lo único que debemos hacer es declarar los argumentos tras la palabra delegate, así:

      button1.Click += delegate(object sender, EventArgs e) { MessageBox.Show(e.ToString()); };

Como se puede apreciar al declarar el método anónimo indicando en el delegado qué tipos de parámetro se necesitan y otorgándoles un nombre es posible hacer uso de ellos sin problemas desde el método anónimo.

 Métodos anónimos (Guía de programación de C#)

En versiones de C# anteriores a la versión 2.0, la única manera de declarar un delegado era utilizar métodos con nombre. C# 2.0 presenta los métodos anónimos, mientras que, en C# 3.0 y versiones posteriores, las expresiones lambda reemplazan a los métodos anónimos como la manera preferente de escribir código insertado. No obstante, la información sobre los métodos anónimos de este tema también se aplica a las expresiones lambda. Hay un caso en el que un método anónimo proporciona una funcionalidad que no se encuentra en las expresiones lambda. Los métodos anónimos permiten omitir la lista de parámetros, y esto significa que un método anónimo se puede convertir en delegados con diversas firmas. Esto no es posible con expresiones lambda

La creación de métodos anónimos es básicamente una forma de pasar un bloque de código como parámetro de delegado. Por ejemplo:

         button1.Click += delegate(System.Object o, System.EventArgs e)

            { System.Windows.Forms.MessageBox.Show("Click!"); };

O bien,

        // Create a delegate instance

        delegate void Del(int x);

 

        // Instantiate the delegate using an anonymous method

        Del d = delegate(int k) { /* … */ };

Mediante los métodos anónimos, se reduce la sobrecarga de codificación al crear instancias de delegados sin tener que crear un método independiente.

Por ejemplo, especificar un bloque de código en vez de un delegado puede ser útil en el caso de que la creación de un método parezca una sobrecarga innecesaria. Un buen ejemplo es cuando se inicia un nuevo subproceso. Esta clase crea un subproceso y también contiene el código que el subproceso ejecuta, sin necesidad de crear un método adicional para el delegado.

        void StartThread()

        {

            System.Threading.Thread t1 = new System.Threading.Thread

              (delegate()

              {

                  System.Console.Write("Hello, ");

                  System.Console.WriteLine("World!");

              });

            t1.Start();

        }

Nota:

El ámbito de los parámetros de un método anónimo es anonymous-method-block.

Es un error utilizar una instrucción de salto, como goto, break o continue, en un bloque de método anónimo cuyo destino está fuera del bloque. También es un error utilizar una instrucción de salto, como goto, break o continue, fuera de un bloque de método anónimo cuyo destino está dentro del bloque.

Las variables locales y los parámetros cuyo ámbito contiene una declaración de método anónimo se denominan variables externas o capturadas del método anónimo. Por ejemplo, en el segmento de código siguiente, n es una variable externa:

     int n = 0;

     Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

A diferencia de las variables locales, el período de duración de la variable externa se extiende hasta que los delegados que hacen referencia a los métodos anónimos cumplan con los requisitos para la recolección de elementos no utilizados. En el momento en que se crea el delegado, se captura el valor de n.

Un método anónimo no puede tener acceso a los parámetros ref u out de un ámbito externo.

No se puede tener acceso a ningún código no seguro dentro de anonymous-method-block.

El ejemplo siguiente muestra las dos maneras de crear instancias de un delegado:

·         Asociar el delegado a un método anónimo.

·         Asociar el delegado a un método con nombre (DoWork).

En cada uno de los casos, se muestra un mensaje cuando se invoca al delegado.

        // Declare a delegate

        delegate void Printer(string s);

 

        class TestClass

        {

            static void Main()

            {

                // Instatiate the delegate type using an anonymous method:

                Printer p = delegate(string j)

                {

                    System.Console.WriteLine(j);

                };

 

                // Results from the anonymous delegate call:

                p("The delegate using the anonymous method is called.");

 

                // The delegate instantiation using a named method "DoWork":

                p = new Printer(TestClass.DoWork);

 

                // Results from the old style delegate call:

                p("The delegate using the named method is called.");

            }

 

            // The method associated with the named delegate:

            static void DoWork(string k)

            {

                System.Console.WriteLine(k)

            }
      }

 

About justindeveloper

I am MCP (Microsoft Certified Professional). MCTS (Microsoft Certified Technology Specialist) and MCPD (Microsoft Certified Professional Developer), also I am SAP Business One Certified!! Desarrollando desde el IDE de Visual Studio NET 2003 hasta ahora con el Visual Studio NET 2010. Desde Microsoft SQL Server 2000 hasta ahora con el Microsoft SQL Server 2008 R2 y tambien con SharePoint, desde WSS 3.0 y MOSS 2007 y ahora familirizandome con el Sharepoint Foundation 2010 & Sharepoint Server 2010. The software development will follow being every time more wonderful!
This entry was posted in Development. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s