viernes, 8 de enero de 2016

Juega Melate con C# (Lottery in C#)

En esta aplicación buscamos seleccionar 6 numero aleatorios en un rango de 56 números. Este es un juego popular en México y se conoce como "Melate", en Norteamérica se le nombra "Lottery". El interés de la aplicación es el uso de la instrucción for. Intente crear el ejemplo, no incluye la prevención de duplicados.

El manejo de ciclos con  for puede ser considerado como controlado por centinela, el cual usted determina cuando hace uso de un contador, definido al inicio de la declaración: limit , el cual se puede ver resaltado en color azul en al siguiente instrucción, y además conoce hasta donde deberá llegar el ciclo, en este caso  el limite es 56.

                                   for (int contador = 0; contador < 56; contador++)

Nota
Esta aplicación tiene una intención de didáctica, no sirve para obtener un resultado real en un juego de estas características.


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

namespace Lottery_Program
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] rango = new int[56];
            int[] seleccionados = new int[6];

            // define un objeto para obtener un numero aleatorio
            Random rnd = new Random();

            // llenado del rango
            for (int i = 0; i < 49; i++)
{
   rango[i] = i + 1;
                Console.WriteLine(rango[i]);
}
         
            // selecciona 6 numeros aleatoriamente
            for (int limit = 0; limit < rango.Length; limit++)
            {
                for (int select = 0; select < 6; select++)
                {
                    seleccionados[select] = rango[rnd.Next(49)];
                }
            }

            Console.WriteLine("Los numeros seleccionados son:");
            for (int j = 0; j < seleccionados.Length; j++)
            {
                Console.Write(" " + seleccionados[j] + " ");
            }
            Console.WriteLine();

        }
    }
}

Polymorphism C# (Polimorfismo en C#)

El polimorfismo como la encapsulación y la herencia son pilares de la programación orientada a objetos. Se puede observar dos situaciones.

Nota
Es muy importante usar los términos de "clase base" y "clase derivada" de forma metódica pues es así como se maneja de manera formal. Evite en lo posible usar otros términos, como


  • En tiempo de ejecución, los objetos instanciados (obtenidos, creados) desde una clase derivada pueden ser manejados como objetos de la clase base, así como los parámetros de los métodos, colecciones y matrices. Cuando esto ocurre, el tipo declarado del objeto ya nos es idéntico a su tipo en tiempo de ejecución.
  • Cuando creamos una clase base podemos escribir (implementar) métodos virtuales. Escribir métodos virtuales se planean con la intención de tener la posibilidad de redefinir en las clases derivadas las operaciones que se realizan internamente en el cuerpo del método, ya que el nombre del método permanece igual, tanto en la clase base como en la derivada, creando con esto un efecto de comportamiento diferente aun cuando la acción que manifiesten tenga el mismo nombre.


Como ejemplo se usa un aplicación con la cual dibujaremos diferentes formas geométricas. Para lo cual:

Crearemos una jerarquía de clases en las que tendremos una clase base, y esta clase base nos ayudara a escribir las clases derivadas.

Escribiremos en nuestra clase base un método como virtual, el cual sera sobre-escrito en las clases derivadas que escribamos; cada clase derivada tendrá su propia implementación, es decir,  instrucciones propias o diferentes dentro del cuerpo del método en las clases derivadas, según convenga a nuestras necesidades, de tal forma que al crear objetos de las clases derivadas (instanciar) y llamar al método, el método tendrá un comportamiento diferente y correspondiente a la clase derivada que usamos.

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

namespace PolimorfismoExample
{
    public class FiguraGeometrica
    {
     

        // metodo virtual
        public virtual void Dibujar()
        {
            Console.WriteLine("Ejecutando el método dibujar desde la clase base.");
        }
    }

    class Circulo : FiguraGeometrica
    {
        public override void Dibujar()
        {
            // Codigo para dibujar un circulo
            Console.WriteLine("Dibujando un circulo");
         
        }
    }

    class Rectangulo : FiguraGeometrica
    {
        public override void Dibujar()
        {
            // Codigo para dibujar un triangulo
            Console.WriteLine("Dibujando un rectangulo");
         
        }
    }

    class Triangulo : FiguraGeometrica
    {
        public override void Dibujar()
        {
            // Codigo para dibujar un triangulo
            Console.WriteLine("Dibujando un triangulo");
         
        }
    }


class Program
    {
        static void Main(string[] args)
        {

            //DerivedClass B = new DerivedClass();
            //B.DoWork();

            //BaseClass A = (BaseClass)B;
            //A.DoWork();


            // Polimorfismo trabajando en su forma 1: un rectangulo,
            // triangulo y circulo
            // pueden ser usados todos juntos como una clase Shape.
            // No es necesario cast porque se puede realizar una
            // conversion implicita desde una clase derivada
            // a su clase base.
            // llmando al método virtual
            FiguraGeometrica fg = new FiguraGeometrica();
            fg.Dibujar();


            List<FiguraGeometrica> shapes = new List<FiguraGeometrica>();
            shapes.Add(new Rectangulo());
            shapes.Add(new Triangulo());
            shapes.Add(new Circulo());


            // Polimorfismo trabajando en su forma 2: el metodo
            // virtual Dibujar es invocado en cada clase derivada
            // no de la clase base.
            foreach (FiguraGeometrica item in shapes)
            {
                item.Dibujar();
            }

            // keep the console in debug mode
            Console.WriteLine("Presione cualquier tecla para terminar.");
            Console.ReadKey();
        }
    }

}

Nota.
En C# cada tipo es polimórfico porque todos los tipos, incluidos los definidos por nosotros al escribirlos, heredan de Object.

Una clase derivada hereda de la clase base, los métodos, campos, propiedades y eventos de la clase base. Cuando diseñamos y escribimos una clase derivada tenemos las siguientes opciones.


  • Invalidar, es decir sobre-escribir por las clases derivadas los miembros de la clase base. Estos miembros deben ser declarados, escritos con la palabra clave virtual o abstract. La palabra clave virtual se usa para métodos, propiedades, indices o eventos y en las clases derivadas se completa con la palabra clave override. La palabra abstract indica que el elemento tiene una implementación incompleta, se puede usar para clases, métodos, propiedades, indices y eventos. Tenga en cuenta que abstract se usa en combinación con definición de clases abstractas.
         Nota
         Los campos no pueden ser virtuales.
  • Heredar el método de la clase base más próximo sin invalidarlo o sobre-escribirlo.
  • Definir una nueva implementación no virtual de esos miembros que oculte la implementación de la clase base.


Al escribir una clase base y crear una clase derivada invalidamos uno de esos miembros, siempre y cuando se den dos cosas, en la clase base el miembro sea hubiera definido como virtual o abstract y en la clase derivada definamos un miembro del mismo nombre usando la palabra clave override. Como se presento en el ejemplo.

Miembros virtuales

En el caso de haber creado un objeto de una clase derivada que ha invalidado un método virtual, el miembro sobre-escrito o invalidado será llamado al realizar una llamada al método desde una conversión del objeto de la clase derivada al de la clase base. Como en el siguiente ejemplo, ehecute con Ctrl+F5.

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

namespace PolimorfismoExample
{


    #region IntroPolimotfismo

    public class BaseClass
    {
        public virtual void DoWork() { Console.WriteLine("Clase Base"); }
        public virtual int WorkProperty
        { get { return 0; } }
    }

    public class DerivedClass : BaseClass
    {
        public override void DoWork() { Console.WriteLine("Clase Derivada"); }
        public override int WorkProperty
        {
            get
            {
                return 1;
            }
        }
    }

    #endregion


    class Program
    {
        static void Main(string[] args)
        {

            DerivedClass B = new DerivedClass();
            B.DoWork();

            BaseClass A = (BaseClass)B;
            A.DoWork();

        }
    }
}

Podemos escribir métodos y propiedades virtuales en clases base para  permiten a las clases derivadas extender una clase base sin necesidad de usar la implementación o las instrucciones del cuerpo del método de la clase base. Con esto obtenemos un comportamiento diferente y adecuado a lo que deseamos en la clase derivada, utilizando nombres iguales pero acciones diferentes. 

Ocultar miembros de la clase base con nuevos miembros
Si queremos utilizar el mismo nombre para un miembro tanto en la clase base como en la derivada pero sin utilizar la palabra clave virtual en la declaración del miembro en la clase base, entonces utilizaremos en la clase deriva la palabra new. La palabra new se coloca antes de la definición del tipo que devolverá el método. Como se ve en el siguiente ejemplo la clase.

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

namespace PolimorfismoExample
{


    #region IntroPolimotfismo

    public class BaseClass
    {
        public void DoWork() { Console.WriteLine("Clase Base"); }
        public virtual int WorkProperty
        { get { return 0; } }
    }

    public class DerivedClass : BaseClass
    {
        public new void DoWork() { Console.WriteLine("Usando NEW en Clase Derivada"); }
        public override int WorkProperty
        {
            get
            {
                return 1;
            }
        }
    }

    #endregion


    class Program
    {
        static void Main(string[] args)
        {

            DerivedClass B = new DerivedClass();
            B.DoWork();

            BaseClass A = (BaseClass)B;
            A.DoWork();

        }
    }
}

Observe que en este caso se hizo una conversión de un objeto B de la clase derivada a un objeto A de la clase base y al llamar al método DoWork desde el objeto A, lo hace de la clase base. Parece un poco enredado,  pero al ejecutar se aclara el efecto.

Evitar que las clases derivadas invaliden (sobre-escriban) los miembros virtuales
Aquellos miembros escritos o definidos como virtuales de una clase permanecen siempre virtuales, no importando cuantas clases derivadas se escriban.  Puede evitar que clases derivadas sobre-escriban métodos sellándolos con la palabra clave sealed y si aun quisiera usar el mismo nombre del método en una clase derivada puede usar la palabra clave new. Como en el siguiente ejemplo

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

namespace SealedClasessExample
{
    /// <summary>
    /// El método HacerAlgo es virtual
    /// </summary>
    public class ClaseBase
    {
        public virtual void HacerAlgo()
        { Console.WriteLine("Soy un objeto de ClaseBase"); }
    }
 
    /// <summary>
    /// La clase nvalida o sobre escribe el método: HacerAlgo
    /// de la clase base
    /// </summary>
    public class ClaseDerivada : ClaseBase
    {
        public override void HacerAlgo()
        { Console.WriteLine("Soy un objeto de ClaseDerivada y herede de ClaseBase"); }
    }

    /// <summary>
    /// El método HacerAlgo ya no es virtual para ninguna clase que derive
    /// desde esta clase
    /// </summary>
    public class ClaseConMetodoSellado : ClaseDerivada
    {
        public sealed override void HacerAlgo()
        { Console.WriteLine("Soy un objeto de ClaseConMetodoSellado y herede de ClaseDerivada"); }
    }

    /// <summary>
    ///  En esta clase se usa la palabra clave: new
    /// para poder usar el nombre del método: HacerAlgo
    /// </summary>
    public class ClaseQueUsaNew : ClaseConMetodoSellado
    {
        public new void HacerAlgo()
        { Console.WriteLine("Soy un objeto de ClaseQueUsaNew y herede de ClaseConMetodoSellado"); }
    }



    class Program
    {
        static void Main(string[] args)
        {
            ClaseBase A = new ClaseBase();
            A.HacerAlgo();

            ClaseDerivada B = new ClaseDerivada();
            B.HacerAlgo();

            ClaseConMetodoSellado C = new ClaseConMetodoSellado();
            C.HacerAlgo();

            ClaseQueUsaNew D = new ClaseQueUsaNew();
            D.HacerAlgo();

        }
    }
}


Intentar sobre-escribir un método sellado se crea un error en la compilación. En la clase ClaseQueUsaNew que deriva de la clase ClaseConMetodoSellado use la palabra clave override en el método HacerAlgo, en vez de new, y compile para que observe el efecto. El resultado es que el compilador le marcará un error, como se puede ver en la siguiente imagen.



Acceso a miembros virtuales desde clase derivadas
Aun cuando una clase derivada hubiera reemplazado, invalidado o sobre-escrito,  un miembro es posible tener acceso a dicho método, para hacerlo se usa la palabra clave base, como se puede ver en el siguiente ejemplo.

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

namespace UsoDeBase
{
    public class ClaseBase
    {
        public virtual void HacerAlgo() { Console.WriteLine("HacerAlgo desde ClaseBase"); }
    }

    public class ClaseDerivada: ClaseBase
    {
        public override void HacerAlgo()
        {
            Console.WriteLine("HacerAlgo desde ClaseDerivada");
            base.HacerAlgo();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ClaseDerivada cd = new ClaseDerivada();
            cd.HacerAlgo();
        }
    }
}

La palabra clave base se usa para obtener acceso a a los miembros de la clase base desde una clase derivada. Se puede utilizar de las siguientes formas

  • Llame a un método de la clase base, reemplazado por otro método en la clase derivada, vea el siguiente ejemplo.
  • Especifique a que constructor de la clase base se debe llamar para crear instancias de la clase derivada.
Para utilizar la palabra clave base solo se permite en un constructor de clase, en un método, en un descriptor de acceso a una propiedad de isntancia  - {get; set; }-.

No es posible utilizar la palabra clave dentro de un método estático.

En C# una clase derivada puede derivar de una y solo una clase base, aunque pueda derivar de múltiples interfaces, que en este momento no se esta tocando este tema. Entonces tenemos que solamente se accede a los miembros de clase base desde a clase derivada; aun si la clase base viene de otra clase base.

En este ejemplo se especifica en el constructor de la clase derivada el constructor de la clase base.

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

namespace UsoDeBaseEnConstructor
{
    public class ClaseBase
    {
        int num;
        public ClaseBase()
        {
            Console.WriteLine("Constructor sin parámetros.");
        }

        public ClaseBase(int i)
        {
            num = i;
            Console.WriteLine("Constructor con parámetros.");
        }

        public int ObtenerNumero()
        {
            return num;
        }
     
    }

    public class ClaseDerivada: ClaseBase
    {
        // este constructor llamara al constructor base
        // sin parámetros
        public ClaseDerivada(): base()
        { }

        // este constructor llamara al constructor base
        // con parámetros
        public ClaseDerivada(int i)
            : base(i) { }

    }


    class Program
    {
        static void Main(string[] args)
        {
            ClaseDerivada cd1 = new ClaseDerivada();
            ClaseDerivada cd2 = new ClaseDerivada(55);
        }
    }
}




Referencia:
https://msdn.microsoft.com/es-MX/library/ms173152.aspx
https://msdn.microsoft.com/es-MX/library/hfw7t1ce.aspx

miércoles, 16 de diciembre de 2015

C# Accessor Delegates Exception

Si usted usa la sintaxis regular de event, el compilador genera el accessor por usted. Esto lo  hace claro que los eventos no son delegados, estos son convenientemente manejados como delegados.

Los delegados son ejecutados en un orden secuencial. Generalmente, los delegados son ejecutados en el orden en que fueron agregados, aunque  esto no es algo que es especifico dentro del Common Language Infraestructure (CLI), no debería depender de esto.

Una cosa que es un resultado directo del orden secuencial de ejecución es el manejo de las excepciones. Como en el siguiente ejemplo tenemos un suscriptor del event lanza un error.

using System;

namespace ExceptionWhenRaisingEvent
{
    public class Pub
    {
        public event EventHandler OnChange = delegate { };
        public void Raise()
        {
            OnChange(this, EventArgs.Empty);
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
                => Console.WriteLine("Suscriptor 1 llamado");

            p.OnChange += (sender, e)
                => { throw new Exception(); };

            p.OnChange += (sender, e)
                => Console.WriteLine("Suscriptor 1 llamado");

            p.Raise();
        }
    }
}



Como puede ver, el primer subscriptor es ejecutado con éxito. el segundo lanza una excepción, y el tercero nunca es llamado.

Si este no es el comportamiento que usted quiere, necesita manualmente lanzar los eventos y manejar cualquier excepción que ocurra. Puede hacer esto usando el método GetInvocationList que es declarado en la clase base System.Delegate

El siguiente ejemplo obtiene los subscriptores y enumera manualmente.
using System;
using System.Collections.Generic;
using System.Linq;


namespace RaiseEventWhitExceptionManual
{
    public class Pub
    {
        public event EventHandler OnChange = delegate { };
        public void Raise()
        {
            var exceptions = new List<Exception>();
            foreach (Delegate handler in OnChange.GetInvocationList())
            {
                try
                {
                    handler.DynamicInvoke(this, EventArgs.Empty);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }
            }

            if (exceptions.Any())
            {
                throw new AggregateException(exceptions);
            }

        }

    }



    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
                => Console.WriteLine("Llamando al Subscriptor 1");

            p.OnChange += (sender, e)
                => { throw new Exception(); };

            p.OnChange += (sender, e)
                => Console.WriteLine("Llamando al Subscriptor 3");

            try
            {
                p.Raise();
            }
            catch (AggregateException ex)
            {
                Console.WriteLine(ex.InnerExceptions.Count);
            }

        }


    }
}
Resultado


Referencia:
Exam Ref 70-483 Programming in C#



C# using event Action delegate

Un popular patrón de diseño (una solución reusable para un problema recurrente) en el desarrollo de una aplicación es el publish-subscribe (editor-subscriptor). Usted subscribe a un evento y después lo notifica cuando el publisher de un evento lanza el nuevo evento. Este es usado para establecer bajo acoplamiento entre componentes es una aplicación.

Los delegados forman la base de un sistema basado en eventos en C#. El siguiente ejemplo presenta como una clase expone un delegado publico y como lanza a éste.

using System;

namespace UsingActionToExposeEvent
{
    public class Pub
    {
        public Action OnChange{get; set;}

        public void Raise()
        {
            if(OnChange != null)
            {
                OnChange();
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += () => Console.WriteLine("Event raised to method 1");
            p.OnChange += () => Console.WriteLine("Event raised to method 2");

            p.Raise();

        }
    }
}

En este ejemplo, la clase Pub lanza el evento. Sin embargo, nada previene a usuarios esternos de la clase lanzar el evento. Tal y como llamamos a p.OnChange, cualquier usuario de la clase puede lanzar el evento para todos los subscriptores.

Para superar estas debilidades, C# usa la palabra clave event. El ejemplo anterior modifica la clase usando la sintaxis event.

using System;

namespace UsingActionToExposeEvent
{
    public class Pub
    {
        public event Action OnChange = delegate { };

        public void Raise()
        {
            if(OnChange != null)
            {
                OnChange();
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += () => Console.WriteLine("Event raised to method 1");
            p.OnChange += () => Console.WriteLine("Event raised to method 2");

            p.Raise();

        }
    }
}

Usando la sintaxis event, hay un par de cambios interesantes. Primero usted deja de usar una propiedad publica pero a un campo publico. Normalmente, este podría ser un paso atras. Sin embargo con la sintaxis event, el compilador protege su campo de un acceso no deseado.

Un evento no puede ser directamente asignado por el operador (con el = en vez del +=). Así no puede tener el riesgo de que alguien remueva a todos los previos subscriptores, así con la sintaxis delegate.

Otro cambio es que los usuarios no externos pueden lanzar su evento. Este puede ser lanzado solamente por aquellos que son parte de la clase que define el evento.

El siguiente ejemplo usa una sintaxis especial par inicializar el evento como un delegado vacio. De esta forma, usted puede remover el nul alrededor del lanzador del evento porque puede ser cierto que el evento sea siempre nulo. Usuarios externos a su clase no pueden definir un valor para el evento nulo, usted puede con seguridad asumir que este siempre tenga un valor.

Hay sin embargo un cambio que debe mantener para seguir las convenciones de codificación den .NET Framework . En vez de usar el tipo Action para su evento, usted debería usar el EventHandler o EventHandler<T>. El EventHandler es declarado como en el siguiente ejemplo.

using System;

namespace CustomEventArguments
{
    public class MyArgs : EventArgs
    {
        public int Value { get; set; }

        public MyArgs(int value)
        {
            Value = value;
        }
    }

    public class Pub
    {
        public event EventHandler<MyArgs> OnChange = delegate { };
        public void Raise()
        {
            OnChange(this, new MyArgs(42));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
            => Console.WriteLine("Event raised: {0}", e.Value);

            p.Raise();
        }
    }
}

La clase Pub usa un EventHandler<MyArgs>, que especifican el tipo de argumentos event. Cuando se lanza este event, usted requiere pasar una instancia de MyAgrs. Suscribirse para el event puede acceder a los argumentos y usar a éste.

Aunque la implementación del event usa un campo publico, usted puede mantenerse en la construcción agregando y removiendo suscriptores. Este es llamado custom event accesor. El siguiente ejemplo crea un para un custom event accesor evento.

NOTA.
Observe de forma detenida  la declaración del delegado, tienen el mismo nombre pero la diferencia esta en que en la declaración del delegado la  primera letra es minúscula: onChange.
La declaración para el manejo del delegado la primera letra es mayúscula: OnChange y tiene el aspecto de una propiedad.

using System;

namespace CustomEventAccessor
{
    public class MyArgs : EventArgs
    {
        public int Value { get; set; }

        public MyArgs(int value)
        {
            Value = value;
        }
    }

    public class Pub
    {
        private event EventHandler<MyArgs> onChange = delegate { };
        public event EventHandler<MyArgs> OnChange
        {
            add
            {
                lock (onChange)
                {
                    onChange += value;
                }
            }

            remove
            {
                lock (onChange)
                {
                    onChange -= value;
                }
            }

        }

        public void Raise()
        {
            onChange(this, new MyArgs(42));
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}



Un custom event accessor se observa como una propiedad con un accessor get. En vez de get y set usted usa add y remove. Es importante colocar un lock en los subscriptores para agregar y remover para hacer segura la operación en un hilo seguro.

Referencia:
Exam Ref. 70-384 Programming in C#










C# delegate, closure

Pensando en algo más complejo, por ejemplo cuando la función lambda hace referencia a variables declaradas fuera de la expresión lambda (o para la referencia this). Normalmente, cuando dejas al alcance de una variable, la variable no es valida. ¿Pero que si un delegado se refiere a una variable local y esta regresa después quien llamo al método? Ahora el delegado tiene una variable de larga vida. El compilador genera código que hace la vida de la variable sea más larga que la vida del delegado esto es llamado closure (cierre).

using System;

namespace UsandoDelegadoAction
{
    class Program
    {
        static void Main(string[] args)
        {
            int myVar = 100;

            Console.WriteLine("myVar antes de llamar a delegado {0}", myVar);

            Action<int, int> calc = (x, y) =>
            {
                //int myVar = 10;

                myVar += (x + y);
                Console.WriteLine("Llamada desde el delegado {0}", myVar);
            };

            calc(3, 4);
            Console.WriteLine("Despues de llamar al delegado {0}", myVar);
        }
    }
}




Si se intenta crear una variable local del mismo nombre a la variable externa, la ayuda inteligente de Visual Studio avisa que no se puede usar, como se ve en la siguiente imagen.



Reference:
Exam Ref. 70-483 Proramming in C#

C# using Action delegate

Algunas veces declaramos un delegado para un evento, sentimos un poco de incomodo de manejar. .NET Framework tiene uun par de tipos delegados preconstruidos que puede usar cuando declare  delegados. Por ejemplo:

public delegate int Calculate(int x, int y )

Es posible reemplazar delegate con un tipo pre-construido Fun<int, int, int>.  El tipo Fun<...> se encuentra en el espacio de nombre System y representa al delegado que regresa un tipo y puede tomar de 0 a16 parámetros. Todos estos tipos heredan desde System.MulticastDelegate asi usted puede agregar métodos para invocar la lista.

Si usted quiere un tipo delegado que no regrese un valor, puede usar el tipo System.Action. Estos pueden tomar de 0 a 16 parámetros, pero ellos no regresan valor un valor.

using System;

namespace UsandoDelegadoAction
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<int, int> calc = (x, y) =>
            {
                Console.WriteLine(x + y);
            };

            calc(3, 4);

        }
    }
}

Referencia:
Exam Ref. 70-483 Programming in  C#





martes, 15 de diciembre de 2015

C# Using lambda expressions

Algunas veces la firma de un método puede tener más código que el solo cuerpo del método. Hay también situaciones en las que usted necesita un método completo solo para usar este en un delegado.

Para estos casos, Microsoft agrego algunas características a C#. En C# 2.0 los métodos anónimos. en C# 3.0, estos vienen a ser aun mejores usando lambda expressions. Las expresiones lambda son la forma preferida cuando se escribe nuevo código.

El siguiente  ejemplo:

using System;

namespace LambdaExpressionCreateDelegate
{
    class Program
    {
        public delegate int Calculate(int x, int y);  

        static void Main(string[] args)
        {
            Calculate calc = (x, y) => x + y;
            Console.WriteLine(calc(3, 4));  // presenta 7
            calc = (x, y) => x * y;
            Console.WriteLine(calc(3, 4)); // presenta 12

        }
    }
}

La expresión en ingles se usa go and goes y se lee: "x and y goes to adding x and y". Voy a realizar una lectura como se haría en un lenguaje cercano al de las matemáticas, se leeria así, "para toda y Yen la expresión se han de sumar y Y".

La función lambda no especifica nombre como los métodos. Es por eso las funciones lambda son llamadas anonymus fuctions (funciones anónimas) . No tiene que especificar un valor de return de forma explicita. El compilador infiere este de forma automática desde su expresión lambda. Y en el caso del ejemplo, los tipos de los parámetros  X y Y pueden no ser especificados de forma explicita.

Como lo puede ver una expresión lambda puede ser compacta. Si la expresión lambda tiene solamente un parámetro, usted puede aun remover los paréntesis alrededor de los parámetros.

Puede crear lambdas que abarquen múltiples declaraciones. Puede hacerlo agregando las llaves ( {} ) alrededor de las declaraciones que forman la lambda. Como en el siguiente ejemplo

using System;

namespace LambdaExpMultipleStatement
{
    class Program
    {
        public delegate int Calculate(int x, int y);

        public static Calculate calc =
            (x, y) =>
            {
                Console.WriteLine("Adding numbers");
                return x + y;
            };

        static void Main(string[] args)
        {
            Console.WriteLine("Resultado de expresion lambda {0} ", calc(3, 4));
        }
    }
}

Referencia:
Exam Ref. 70-483 Programming in C#