Exemplo n.º 1
0
        static void Main(string[] args)
        {
            EncabezadoYPieConsola Escritor = new EncabezadoYPieConsola();

            #region Ejemplo 5.1
            //Ejemplo de Swap usando una generic function llamada Swap
            //ver la dfinición más abajo
            Escritor.EscribirEncabezado("Ejamplo 5.1: Swap usando generics");
            int x = 2;
            int y = 3;
            System.Console.WriteLine("Inicialmente x es: {0}, e y es {1}", x.ToString(), y.ToString());
            //Esta función se puede llamar como se llama debajo o así: Swap<int>(ref x, ref y);
            Swap(ref x, ref y);
            System.Console.WriteLine("Ahora x es: {0}, e y es {1}", x.ToString(), y.ToString());
            Escritor.EscribirPie("Fin de Ejemplo 5.1");
            #endregion


            //Ejemplo de uso de la función genérica
            var accounts = new List <Account>()
            {
                new Account("Moe", 11.40M),
                new Account("Curly", 20.50M),
                new Account("Larry", 50.15M)
            };

            decimal sum = Algorithms.SimpleAccumulate(accounts);
            System.Console.WriteLine("Total: {0}", sum.ToString());

            int  uno        = 1;
            int? algo       = uno;
            bool tieneValor = algo.HasValue;
        }
Exemplo n.º 2
0
        static void Main(string[] args)
        {
            EncabezadoYPieConsola separador = new EncabezadoYPieConsola();

            //Ejemplo 1: Dos maneras de iterar en un array
            #region Ejemplo 1
            separador.EscribirEncabezado("Ejemplo 1: Dos maneras de iterar en un array");
            int[] myArray = { 0, 1, 2, 3 };
            for (int i = 0; i < myArray.Length; i++)
            {
                Console.WriteLine(myArray[i].ToString());
            }

            foreach (var item in myArray)
            {
                Console.WriteLine(item.ToString());
            }
            separador.EscribirPie("Fin Ejemplo 1");
            #endregion

            //Ejemplo 2: Maneras de reservar espacio en memoria para un array de User-Defined Types (UDTs)
            #region Ejemplo 2
            separador.EscribirEncabezado("Ejemplo 2: Array de UDTs");
            Person[] myPersons = new Person[2];
            //Si intento acceder a los elmentos del array antes de incializarlos tengo un error
            //El ciclo forach ejecutado aqui antes de inicializar los elementos me daría NullReferenceException

            myPersons[0] = new Person {
                FirstName = "Albert", LastName = "Einstein"
            };
            myPersons[1] = new Person {
                FirstName = "Erwin", LastName = "Schrödinger"
            };

            foreach (Person item in myPersons)
            {
                Console.WriteLine(item.ToString());
            }


            Person[] newPersons = { new Person {
                                        FirstName = "Albert", LastName = "Einstein"
                                    },
                                    new Person {
                                        FirstName = "Erwin", LastName = "Schrödinger"
                                    } };


            foreach (Person item in newPersons)
            {
                Console.WriteLine(item.ToString());
            }
            separador.EscribirPie("Fin de ejemplo 2");
            #endregion

            //Ejemplo 3: Arrays multidimensionales rectangulares (todas las filas tienen la misma cantidad de columnas)
            #region Ejemplo 3
            separador.EscribirEncabezado("Ejemplo 3: Arrays multidimensionales recatngulares");
            int[,] twoDim = new int[, ] {
                { 0, 1 },
                { 2, 3 }
            };

            for (int row = 0; row < twoDim.Length / 2; row++)
            {
                for (int col = 0; col < twoDim.Length / 2; col++)
                {
                    Console.WriteLine(twoDim[row, col].ToString());
                }
            }

            //Tambien se podría escribir
            //int[,,] threeDim;
            //int[,,,] fourDim;
            //Pero en estos casos es mejor usar CreateInstance
            separador.EscribirPie("Fin Ejemplo 3");
            #endregion

            //Ejemplo 4: Jagged Arrays (arrays donde cada fila puede tener un número de columnas diferente)
            #region Ejemplo 4
            separador.EscribirEncabezado("Ejemplo 4: Jagged Arrays");
            int[][] jagged = new int[3][];
            jagged[0] = new int[2] {
                0, 1
            };
            jagged[1] = new int[3] {
                2, 3, 4
            };
            jagged[2] = new int[2] {
                5, 6
            };

            for (int row = 0; row < jagged.Length; row++)
            {
                for (int col = 0; col < jagged[row].Length; col++)
                {
                    Console.Write(jagged[row][col].ToString() + " ");
                    if (col == jagged[row].Length - 1)
                    {
                        Console.Write("\n");
                    }
                }
            }
            separador.EscribirPie("Fin Ejemplo 4");
            #endregion


            //Ejemplo 5: Sort simple. Los tipos primitivos proveen un método CompareTo y llamando al método Sort se ordenan
            #region Ejemplo 5
            separador.EscribirEncabezado("Ejemplo 5: Sort simple usando CompareTo de Tipos Primitivos");
            string[] cantantes = new string[] { "Glen Hughes", "Joe Linterna", "Jon Anderson", "Ian Gillan" };

            Array.Sort(cantantes);

            foreach (var cantante in cantantes)
            {
                Console.WriteLine(cantante);
            }
            separador.EscribirPie("Fin de Ejemplo 5");
            #endregion

            //Ejemplo 6: En un array de objetos tengo que hacer que el tipo definido x el usuario
            //implemente ISortable y provea una implementación de CompareTo (ver la definición de SortablePerson
            #region Ejemplo 6
            separador.EscribirEncabezado("Ejemplo 6: Ordenamiento usando método CompareTo del UDT");
            SortablePerson[] SortablePersons = new SortablePerson[]
            {
                new SortablePerson {
                    FirstName = "Jon", LastName = "Anderson"
                },
                new SortablePerson {
                    FirstName = "Jon", LastName = "Bon Jovi"
                },
                new SortablePerson {
                    FirstName = "Ian", LastName = "Anderson"
                },
                new SortablePerson {
                    FirstName = "Ian", LastName = "Gillan"
                }
            };

            Array.Sort(SortablePersons);
            foreach (var sortablePerson in SortablePersons)
            {
                Console.WriteLine(sortablePerson.ToString());
            }
            separador.EscribirPie("Fin de Ejemplo 6");
            #endregion


            //Ejemplo 7: Inicializo un array usando CreateInstance. Ver que todo el código referido al array usa Object
            //tanto para setear el tipo de elemento, como para recuperarlo. Es decir, el código del array es independiente
            //del tipo que guardo en el array. GetValue devuelve un Object. CreateInstance tiene varias sobrecargas
            //para crear arrays multidimensionales y crear arrays que no son zero-based
            #region Ejemplo 7
            separador.EscribirEncabezado("Ejemplo 7: Uso de CreateInstance");

            object myObject;
            int    myInt = 5;
            myObject = myInt;
            Array  thisArray = Array.CreateInstance(myObject.GetType(), 5); //Si supiera el tipo pondría por ejemplo typeof(int), pero la idea aquí es que desconozco el tipo, por eso uso el GetType
            object valor;
            int    entero = 12;
            valor = entero;
            thisArray.SetValue(valor, 0); //Uso de SetValue para fijar el valor. De nuevo uso un Object para recibir el valor
            entero = 69;
            valor  = entero;
            thisArray.SetValue(valor, 1);

            for (int i = 0; i < thisArray.Length; i++)
            {
                valor = thisArray.GetValue(i);
                Console.WriteLine("Este es el valor: {0}", valor.ToString()); //No inicialicé los valores, pero como esta boxed, esto no me da error
            }

            separador.EscribirPie("Fin de Ejemplo 7");
            #endregion


            //Ejemplo 7b: Casteo el Array obtenido con CreateInstance a un array de enteros. A ver:
            #region Ejemplo 7b
            separador.EscribirEncabezado("Ejemplo 7b: Casteo del objeto Array");

            int[] arrayDeEnteros = (int[])thisArray;
            //A pesar de tener objetos sin inicializar, se castean al valor default del int que es cero
            for (int i = 0; i < arrayDeEnteros.Length; i++)
            {
                Console.WriteLine("Después de castearlo, valor: {0}", arrayDeEnteros[i].ToString());
            }

            separador.EscribirPie("Fin de Ejemplo 7b)");
            #endregion


            //Ejemplo 8: Arrays multidimensionales con CreateInstance
            //Primero creo un array unidimensional que especifica el número de elementos en cada coordenada. Lo llamo coordenadas
            //Es un objeto Array, creado con CreateInstance y esto es diferente a un int[]. Cuando lo pase como argumento
            //en la segunda llamada a CreateInstance, lo tenga que castear a int[]. Es un poco excesivo de mi parte. Este array que
            //representa las coordenadas se puede crear de tipo int directamente
            #region Ejemplo 8
            separador.EscribirEncabezado("Ejemplo 8: Arrays multidimensionales con CreateInstance");

            Array coordenadas = Array.CreateInstance(typeof(int), 2);                          //Creación del array de coordenadas
            coordenadas.SetValue(1, 0);                                                        //Valor del primer elemento: el array que voy a crear tendrá 1 fila
            coordenadas.SetValue(2, 1);                                                        //Valor del segundo elemento: el array que voy a crear tendrá 2 columnas
            Array otroArrayMas = Array.CreateInstance(myObject.GetType(), (int[])coordenadas); //usé myObject creado en el ejemplo 7
            //A partir de acá puedo fijar y obtener valores como antes
            otroArrayMas.SetValue(11, new int[] { 0, 0 });                                     //Fijo el valor del primer elemento
            //Fijate que uso un array para indicar las coordenadas
            otroArrayMas.SetValue(12, new int[] { 0, 1 });
            Console.WriteLine("Valores de otroArrayMas: {0}", otroArrayMas.GetValue(new int[] { 0, 0 }));
            Console.WriteLine("Valores de otroArrayMas: {0}", otroArrayMas.GetValue(new int[] { 0, 1 }));

            separador.EscribirPie("Fin Ejemplo 8");
            #endregion


            //Ejemplo 8b: Arrays Multidimensionales usando CreateInstance
            //Un ejemplo con un poco más de detalle
            #region Ejemplo 8.b)
            separador.EscribirEncabezado("Ejemplo 8b: CreateInstance, más detalles");

            //Array de Coordenadas (2 x 3)
            Array miArrayDeInts = Array.CreateInstance(typeof(int), new int[3] {
                2, 2, 2
            });
            Random miRandom = new Random(DateTime.Now.Millisecond);
            int    randomInt;
            for (int x = 0; x < 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    for (int z = 0; z < 2; z++)
                    {
                        randomInt = miRandom.Next(9);
                        miArrayDeInts.SetValue(randomInt, x, y, z);
                    }
                }
            }

            for (int x = 0; x < 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    for (int z = 0; z < 2; z++)
                    {
                        Console.WriteLine("Valor en: {0},{1},{2}: {3}", x.ToString(), y.ToString(), z.ToString(),
                                          miArrayDeInts.GetValue(x, y, z).ToString());
                    }
                }
            }

            separador.EscribirPie("Fin Ejemplo 8.b");
            #endregion

            //Ejemplo 8.c) Crear un array que no es zero-based
            #region Ejemplo 8.c)
            separador.EscribirEncabezado("Ejemplo 8.c) Crear un array que no es zero-based");

            //Primero creamos un array para fijar las coordenadas
            //Este array va a tener 5 dimensiones
            int[] coordenadasArray = new int[5] {
                1, 2, 3, 4, 5
            };
            //Ahora creamos un array para el límite inferior de cada coordenada
            //Las coordenadas impares tienen un límite inferior de uno (1), las pares de cero (0)
            int[] limitesInferiores = new int[5] {
                1, 0, 1, 0, 1
            };
            //Ahora creo un array
            Array arrayEspecial = Array.CreateInstance(typeof(int), coordenadasArray, limitesInferiores);
            //Por ultimo puedo fijar los valores
            arrayEspecial.SetValue(5, new int[] { 1, 0, 1, 0, 1 });
            arrayEspecial.SetValue(6, new int[] { 1, 1, 1, 0, 1 });
            Console.WriteLine("El valor 10101 es: {0}", arrayEspecial.GetValue(new int[] { 1, 0, 1, 0, 1 }));
            Console.WriteLine("El valor 11101 es: {0}", arrayEspecial.GetValue(new int[] { 1, 1, 1, 0, 1 }));

            separador.EscribirPie("Fin Ejemplo 8.c)");
            #endregion


            //Ejemplo 9: Usando el array SortablePersons del ejemplo 6, creo una copia usando Clone, y otra usando Copy
            //Ojo que al crear el Clone hay que hacer un casting porque de lo contrario se crean de tipo Object[]
            //Luego hago lo mismo, pero usando Copy. Con respecto a Copy recordar que es un método estático
            #region Ejemplo 9
            separador.EscribirEncabezado("Ejemplo 9: Shallow Copy de Arrays");

            SortablePerson[] sortablePersonsClone = (SortablePerson[])SortablePersons.Clone();
            foreach (var unaPersona in sortablePersonsClone)
            {
                Console.WriteLine("Nombre del Clon: {0}", unaPersona.FirstName + " " + unaPersona.LastName);
            }

            SortablePerson[] sortablePersonsCopy = new SortablePerson[4];
            Array.Copy(SortablePersons, sortablePersonsCopy, 4);

            foreach (var unaPersona in sortablePersonsCopy)
            {
                Console.WriteLine("Nombre de la Copia: {0}", unaPersona.FirstName + " " + unaPersona.LastName);
            }

            separador.EscribirPie("Fin de Ejemplo 9");
            #endregion

            //Ejemplo 10: La característica de Covarianza de los Arrays puede llevar a un error en runtime
            //del cual el compilador no se percata
            //La última línea de este ejemplo da un Type Mismatch
            #region Ejemplo 10
            object[]         objectArray;
            SortablePerson[] PersonArrayTest = new SortablePerson[3];
            objectArray    = PersonArrayTest;
            objectArray[0] = new SortablePerson();
            //La siguiente línea daría un error
            //objectArray[1] = "Una string de prueba";
            #endregion

            //Ejemplo 11: Segmentos de Arrays. En este caso creo un segmento pasando dos segmentos
            //uno de cada array de enteros creado al principio
            //Es decir, el segmento está creado por la unión de dos segmentos
            //Esto me muestra el constructor que supongo es más habitual usar:
            //new ArraySegment<int>(arrayOriginal, offset, count)
            //En este ejemplo, se crea un array de segmentos de array
            //new ArraySegment<int>[]{new Arraysegment<int>(enterosPares, 1, 2),
            //new Arraysegment<int>(enterosImpares, 1, 2)}
            #region Ejemplo 11
            separador.EscribirEncabezado("Ejemplo 11: Segmentos de Arrays");

            int[] enterosImpares    = { 1, 3, 5, 7, 9 };
            int[] enterosPares      = { 0, 2, 4, 6, 8 };
            var   segmentoDeEnteros = new ArraySegment <int>[]
            { new ArraySegment <int> (enterosImpares, 1, 2),
              new ArraySegment <int>(enterosPares, 1, 2) };

            Console.WriteLine("La manera siguiente de enumerar los elementos del segmento de array no funciona");
            for (int i = 0; i < segmentoDeEnteros.Length; i++)
            {
                Console.WriteLine("Valor de Elemento {0}: {1}", i.ToString(), segmentoDeEnteros[i].ToString());
            }
            Console.WriteLine("Esta es la correcta:");

            int segmentOffset;
            int segmentCount;

            segmentOffset = segmentoDeEnteros[0].Offset;
            segmentCount  = segmentoDeEnteros[0].Count;
            for (int i = segmentOffset; i < segmentOffset + segmentCount; i++)
            {
                Console.WriteLine("Este es el valor del elemento {0} del primer segmento: {1}", i.ToString(), segmentoDeEnteros[0].Array[i].ToString());
            }


            segmentOffset = segmentoDeEnteros[1].Offset;
            segmentCount  = segmentoDeEnteros[1].Count;
            for (int i = segmentOffset; i < segmentOffset + segmentCount; i++)
            {
                Console.WriteLine("Este es el valor del elemento {0} del segundo segmento: {1}", i.ToString(), segmentoDeEnteros[1].Array[i].ToString());
            }


            separador.EscribirPie("Fin Ejemplo 11");
            #endregion

            //Ejemplo 12: Comparaciones
            //Para comparar dos arrays lo mejor es usar IStructuralEquatable
            //que me permite comparar dos arrays en secuencia. Es decir, la secuencia de elementos en el array tiene
            //que ser la misma. Si están desordenados, aunque los valores sean iguales, la comparación indica que son distintos
            //Con las tuplas puedo usar Equals también, lo cual con arrays no funciona porque compara por referencia
            //De todos modos, usar siempre IStructuralEquatable
            #region Ejemplo 12
            separador.EscribirEncabezado("Ejemplo 12: Comparaciones de Arrays");

            int[] enterosComparacion          = { 1, 3, 5, 7, 9 };
            int[] enterosComparacionInvertida = { 9, 7, 5, 3, 1 };

            Console.WriteLine("Comparación usando: StructuralComparisons.StructuralEqualityComparer.Equals(arg1, arg2)");
            Console.WriteLine("Comparación entre enterosImpares y enterosComparacion: {0}",
                              StructuralComparisons.StructuralEqualityComparer.Equals(enterosImpares, enterosComparacion));

            Console.WriteLine("Comparación entre enterosPares y enterosComparacion: {0}",
                              StructuralComparisons.StructuralEqualityComparer.Equals(enterosPares, enterosComparacion));

            Console.WriteLine("Comparación entre enterosPares y enterosComparacionInvertida: {0}",
                              StructuralComparisons.StructuralEqualityComparer.Equals(enterosPares, enterosComparacionInvertida));

            //Otro modo de comparar los arays de enteros
            Console.WriteLine("Otro modo de comparar: enterosImpares as IStructuralEquatable).Equals(enterosComparacion, EqualityComparer<int>.Default");
            if ((enterosImpares as IStructuralEquatable).Equals(enterosComparacion, EqualityComparer <int> .Default))
            {
                Console.WriteLine("Siguen siendo iguales: enterosImpares y EnterosComparacion");
            }
            else
            {
                Console.WriteLine("enterosImpares y EneterosComparacion no son iguales!?");
            }

            //Ahora hago un sort de los arrays enterosImpares y enterosComparacionInvertida para que me den iguales
            //Si no quiero alterar los arrays, debería implementar un método que los clone a ambos y que los ordene
            //y comparo los elementos clonados
            Array.Sort <int>(enterosComparacion);
            Array.Sort <int>(enterosComparacionInvertida);

            Console.WriteLine("Comparación entre enterosImpares y enterosComparacionInvertida luego de hacer un Sort: {0}",
                              StructuralComparisons.StructuralEqualityComparer.Equals(enterosImpares, enterosComparacionInvertida));


            //Comparación de Tuplas

            var t1 = Tuple.Create <int, string>(1, "tonto");
            var t2 = Tuple.Create <int, string>(1, "tonto");
            var t3 = Tuple.Create <string, int>("tonto", 1);

            Console.WriteLine("Comparación entre t1 y t2: {0}",
                              StructuralComparisons.StructuralEqualityComparer.Equals(t1, t2));

            Console.WriteLine("Comparación entre t1 y t3: {0}", StructuralComparisons.StructuralEqualityComparer.Equals(t1, t3));


            //Comparación de Referencias. Esto da True
            int    unEntero   = 5;
            object unObjeto   = unEntero;
            object otroObjeto = unEntero;
            Console.WriteLine(unObjeto.Equals(otroObjeto));

            separador.EscribirPie("Fin Ejemplo 12");
            #endregion


            //Ejemplo 13: Enumeración y Enumeración inversa
            //La manera sencilla de enumerar Arrays es con foreach
            //foreach no permite enumerar en forma inversa, para eso tengo que crear mi propia clase
            #region Ejemplo 13
            separador.EscribirEncabezado("Ejemplo 13; Enumeraciones");

            //Primero definimos un array con números random del 0 al 100
            int[]  arrayAleatorio = new int[25];
            Random asignador      = new Random(DateTime.Now.Millisecond);

            for (int i = 0; i < arrayAleatorio.Length; i++)
            {
                arrayAleatorio[i] = asignador.Next(100);
            }


            //Ahora enumeramos
            //Primero en forma directa
            Console.WriteLine("Enumeración directa");
            foreach (var enteroAleatorio in arrayAleatorio)
            {
                Console.WriteLine(enteroAleatorio.ToString());
            }



            separador.EscribirPie("Fin Ejemplo 13");
            #endregion


            //Ejemplo 14: Enumeradores personalizados
            //Se muestra el uso de Yield y la definición de enumeradores personalizados
            #region Ejemplo 14
            separador.EscribirEncabezado("Ejemplo 14: Enumeradores personalizados");

            SerieDeEnteros miSerie = new SerieDeEnteros(50, 10);
            Console.WriteLine("Enumeración Directa:");
            string linea = "";
            foreach (var miEntero in miSerie)
            {
                linea += miEntero.ToString() + ", ";
            }
            Console.WriteLine(linea);
            Console.WriteLine("Enumeración inversa:");
            linea = "";
            foreach (var miEntero in miSerie.EnumeracionReversa())
            {
                linea += miEntero.ToString() + ", ";
            }
            Console.WriteLine(linea);

            Console.WriteLine("Enumerar Pares");
            linea = "";
            foreach (var miEnteroPar in miSerie.EnumerarPares())
            {
                linea += miEnteroPar.ToString() + ", ";
            }
            Console.WriteLine(linea);

            separador.EscribirPie("Fin de Ejemplo 14");
            #endregion


            //Ejemplo 15: Comparo dos arrays de UDTs usando la clase PersonasComparables
            //que está mal nombrada, debería haber sido en singlular
            #region Ejemplo 15
            separador.EscribirEncabezado("Ejemplo 15: Comparación estructural de Arrays de UDTs");

            Console.WriteLine("Comparamos dos arrays de UDTs estructuralmente");
            var jlb = new PersonasComparables {
                Apellido = "Borges", Nombre = "Jorge Luis"
            };

            PersonasComparables[] unasPersonas =
            {
                new PersonasComparables {
                    Apellido = "Asimov", Nombre = "Isaac"
                },
                jlb
            };

            PersonasComparables[] otrasPersonas =
            {
                jlb,
                new PersonasComparables {
                    Nombre = "Isaac",Apellido                   = "Asimov"
                }
            };

            Console.WriteLine("Primero comparo con un simple '=='. Esto compara referencias, debe dar distinto");
            if (unasPersonas == otrasPersonas)
            {
                Console.WriteLine("Las referencias son iguales! (WTF)");
            }
            else
            {
                Console.WriteLine("Las referencias son distintas, como cabía esperar");
            }

            Console.WriteLine("Ahora usamos una comparación con el código de Stack Overflow");
            Console.WriteLine("Recorda que va using System.Cllections");

            bool sonIguales = StructuralComparisons.StructuralEqualityComparer.Equals(unasPersonas, otrasPersonas);

            Console.WriteLine("Son iguales? Respuesta: {0}", sonIguales.ToString());
            //Recordemos que hay que ordenarlos para compararlos
            Array.Sort <PersonasComparables>(unasPersonas);
            Array.Sort <PersonasComparables>(otrasPersonas);
            sonIguales = StructuralComparisons.StructuralEqualityComparer.Equals(unasPersonas, otrasPersonas);
            Console.WriteLine("Comparación luego de ordenar. Son iguales? Respuesta: {0}", sonIguales.ToString());

            //Ahora usamos la comparación del libro
            sonIguales = false;
            sonIguales = (unasPersonas as IStructuralEquatable).Equals(otrasPersonas as IStructuralEquatable,
                                                                       EqualityComparer <PersonasComparables> .Default);
            Console.WriteLine("Comparación según el libro. Son iguales? Respuesta: {0}", sonIguales.ToString());


            Console.WriteLine("Este es el primero: {0}", unasPersonas[0].ToString());
            Console.WriteLine("Este es el segundo: {0}", unasPersonas[1].ToString());


            separador.EscribirPie("Fin Ejemplo 15");
            #endregion
        }
Exemplo n.º 3
0
        static void Main(string[] args)
        {
            EncabezadoYPieConsola Separador = new EncabezadoYPieConsola();

            //Ejemplo 1: Diferencia entre prefix y postfix
            //Con el prefijo, primero se suma 1 a x y luefo se evalúa el if
            //con el sufijo primero se evalúa el if y luego se suma 1 a x
            #region Ejemplo 1
            Separador.EscribirEncabezado("Ejemplo 1: Operador prefix y postfix");

            int x = 5;
            if (++x == 6)
            {
                Console.WriteLine("x es igual a 6 con el prefix");
            }
            if (x++ == 7)
            {
                Console.WriteLine("x es igual a 7 con el postfix");
            }
            else
            {
                Console.WriteLine("El operador postfix no incrementó el valor!");
            }

            Separador.EscribirPie("Fin Ejemplo 1");
            #endregion

            //Ejemplo 2: Overflow y como prevenirlo con checked
            #region Ejemplo 2
            Separador.EscribirEncabezado("Ejemplo 2: Overflow y prevención");

            //Aquí unByte hace overflow y termina valiendo cero
            byte unByte = 255;
            Console.WriteLine("Antes del operador, el Byte vale: {0}", unByte.ToString());
            unByte++;
            Console.WriteLine("Ahora el byte vale {0}", unByte.ToString());

            //Aquí otroByte sigue valiendo 255
            //Ver la técnica de encerrar el bloque checked dentro de un try
            //Esto permite atrapar el error eventual que purde producirse al realizar la
            //operación

            byte otroByte = 255;
            try
            {
                checked
                {
                    otroByte++;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Ocurrió la siguiente excepción: {0}", e.Message);
            }
            Console.WriteLine("El valor de otroByte es: {0}", otroByte.ToString());

            Separador.EscribirPie("Fin Ejemplo 2");
            #endregion

            //Ejemplo 3: Conversión explícita usando "as"
            //Ojo sólo se usa para Reference Types
            #region Ejemplo 3
            Separador.EscribirEncabezado("Ejemplo 3: Conversión explícita usando 'as'");

            object miEntero = "5";
            object str      = 12;

            Console.WriteLine("Conversión de object a string: {0}", (miEntero as string) + " es ahora una string");

            if (str as int? != null)
            {
                Console.WriteLine("La conversión de object a 'int?' me anuló la variable");
            }
            else
            {
                Console.WriteLine("Conversión de object a int: {0}", ((str as int?) + 5).ToString());
            }



            Separador.EscribirPie("Fin ejemplo 3");
            #endregion

            //Ejemplo 4: Pérdida de precisión al convertir de long a float
            #region Ejemplo 4
            Separador.EscribirEncabezado("Ejemplo 4: Pérdida de precisión en conversiones");

            long enteroLargo = 922337293685477580;
            Console.WriteLine("EnteroLargo vale: {0}", enteroLargo.ToString());
            float flotante = enteroLargo;
            Console.WriteLine("Flotante vale: {0}", flotante.ToString());
            Console.WriteLine("Prestar atención al redondeo que hizo: 922337293685477580 pasó a ser: 92233730000000000");

            Separador.EscribirPie("Fin Ejemplo 4");
            #endregion

            //Ejemplo 5: Parseo de strings usando el método Parse.
            //Notar que Parse es un método estático de los tipos a los cuales
            //quiero convertir la string. En el ejemplo, de bool y de int
            #region Ejemplo 5
            Separador.EscribirEncabezado("Ejemplo 5: Parseo de Strings usando el método Parse de los tipos primitivos");

            string strBooleano = "true";
            string strEntero   = "16";

            //Probemos conversiones explícitas por medio de parse
            if (bool.Parse(strBooleano))
            {
                Console.WriteLine("El booleano se parseó correctamente");
            }

            if (int.Parse(strEntero) == 16)
            {
                Console.WriteLine("El entero se parseó correctamente");
            }

            Separador.EscribirPie("Fin Ejemplo 5");
            #endregion


            //Ejemplo 6: Un overflow en unboxing
            //Fijate que en la línea donde asigno byteGrandeUnboxed tengo un doble cast:
            //El primero es para pasar byteGrandeBoxed a byte y poder sumarle 1
            //El segundo es para pasar el resultado de la suma a Byte, ya que el compilador lo convierte a int
            //En la segunda parte del ejemplo obtenemos un InvalidCastException al hacer unboxing con un tipo diferente al inicial
            #region Ejemplo 6
            Separador.EscribirEncabezado("Ejemplo 6: Overflow en Unbozing");

            byte   byteGrande        = 255;
            object byteGrandeBoxed   = (object)byteGrande;
            byte   byteGrandeUnboxed = (byte)((byte)byteGrandeBoxed + 1);
            Console.WriteLine("Sorpresa! byteGrandeUnboxed vale: {0}", byteGrandeUnboxed.ToString());

            long   unLongCualquiera      = 333333423;
            object unLongCualquieraBoxed = (object)unLongCualquiera;
            //La siguiente línea da una excpción, por eso está comentada
            //int aDisney = (int)unLongCualquieraBoxed;

            Separador.EscribirPie("Fin ejemplo 6");
            #endregion

            //Ejemplo 7: Comparando objetos
            //En el primer caso comparo por referencia usando el método static de System.Object ReferenceEquals
            //En la segunda y tercera comparaciones uso un método virtual overrideado en la clase Person
            //El override es simple cuando comparo objeto por objeto, no hace falta implementar interfases
            //como se vio en Arrays
            #region Ejemplo 7
            Separador.EscribirEncabezado("Ejemplo 7: Comparaciones de Objetos");

            Person curly = new Person(Person.HashType.Fijo);
            curly.FirstName = "Curly";
            curly.LastName  = "Howard";
            Person otraRef = curly;
            Console.WriteLine("Las dos variables: curly y otraRef son referencias a un mismo objeto de tipo Person");
            Console.WriteLine("Pregunta: las referencias de curly y otraRef son iguales (por medio de ReferenceEquals)? Respuesta: {0}", object.ReferenceEquals(curly, otraRef));
            Console.WriteLine("Comparación por medio de Equals. Son iguales? Respuesta: {0}", (curly.Equals(otraRef)).ToString());
            Console.WriteLine("Comparación por medio de '=='. Son iguales? Respuesta: {0}", (curly == otraRef).ToString());


            Person shemp = new Person(Person.HashType.Fijo);
            shemp.FirstName = "Shemp";
            shemp.LastName  = "Howard";
            Console.WriteLine("En este caso las variables: curly y shemp apuntan a dos instancias distintas de la clase Person");
            Console.WriteLine("Comparación de curly vs shemp por medio de Equals. Son iguales? {0}", (shemp.Equals(curly)));
            Console.WriteLine("Comparación de curly vs shemp por medio de '=='. Son iguales? {0}", (shemp == curly).ToString());
            Console.WriteLine("Hash de Curly: {0}", curly.GetHashCode().ToString());
            Console.WriteLine("Hash de Shemp: {0}", shemp.GetHashCode().ToString());

            Person curlyClon = new Person(Person.HashType.Algoritmo);
            curlyClon.FirstName = "Curly";
            curlyClon.LastName  = "Howard";

            Console.WriteLine("Comparación de Curly vs CurlyClon por medio de Equals. Son iguales? {0}", (curlyClon.Equals(curly)));
            Console.WriteLine("Comparación de Curly vs CurlyClon por medio de '=='. Son iguales? {0}", (curlyClon == curly).ToString());
            Console.WriteLine("Hash de Curly: {0}", curly.GetHashCode().ToString());
            Console.WriteLine("Hash de CurlyClon: {0}", curlyClon.GetHashCode().ToString());

            Separador.EscribirPie("Fin Ejemplo 7");
            #endregion

            //Ejemplo 8: Comparación de value types usando Equals de instancia (no se precisa castear, se hace boxing)
            #region Ejemplo 8
            Separador.EscribirEncabezado("Ejemplo 8: Comparación de Value Types");

            int primerEntero  = 5;
            int segundoEntero = 5;
            Console.WriteLine("Comparación de dos enteros usando Equals de instancia, equals de ReferenceType y '=='");
            Console.WriteLine("P: Son iguales (Equals de instancia)? R: {0}", (primerEntero.Equals(segundoEntero)).ToString());
            Console.WriteLine("P: Son iguales (Equals de ValueType)? R: {0}", (ValueType.Equals(primerEntero, segundoEntero)).ToString());
            Console.WriteLine("P: Son iguales (==)? R: {0}", (primerEntero == segundoEntero).ToString());


            //Segunda parte del ejemplo: Comparando structs con el Equals de instancia
            Console.WriteLine("Segunda parte: comparación de Structs (son value types). Dos instancias distintas con el mismo contenido");
            MisMascotas mascotasReales = new MisMascotas();
            mascotasReales.NombreDelGato  = "Wanda";
            mascotasReales.NombreDelPerro = "Barbie";

            MisMascotas mascotasImaginarias = new MisMascotas();
            mascotasImaginarias.NombreDelGato  = "Wanda";
            mascotasImaginarias.NombreDelPerro = "Barbie";

            Console.WriteLine("P: Son iguales las dos instancias (utilizando Equals de instancia)? R: {0}", (mascotasReales.Equals(mascotasImaginarias)).ToString());
            Console.WriteLine("P: Son iguales las dos instancias (utilizando Equals de ValueType)? R: {0}", (ValueType.Equals(mascotasImaginarias, mascotasReales)).ToString());



            Separador.EscribirPie("Fin Ejemplo 8");
            #endregion

            //Ejemplo 9: Operator Overloading para un vector en 3D
            //EN verdad lo más importante está en la definición del struct vector, que es donde está el overload
            #region Ejemplo 9
            Separador.EscribirEncabezado("Ejemplo 9: Sobrecarga de operadores en clases");

            Vector velocidad          = new Vector(1, 2, 3);
            Vector velocidadAdicional = new Vector(4, 5, 6);
            Vector velocidadFinal     = velocidad + velocidadAdicional;
            Console.WriteLine("El resultado es: {0}", velocidadFinal.ToString());

            Separador.EscribirPie("Fin de ejemplo 9");
            #endregion

            //Ejemplo 9b: Este código muestra una peculiaridad del producto con respecto a la operación XOR
            //Multiplicar por cero un valor no nulo y después hacer un XOR no es lo mismo que hacer un XOR con cero
            #region Ejemplo 9b
            var result  = 0;
            var result2 = 0;
            result = (result * 397) ^ 41;
            result = (result * 397) ^ 37;
            Console.WriteLine(result.ToString());
            Console.WriteLine((result2 * 397).ToString());
            #endregion

            //Ejemplo 10: Conversión con System.Convert
            //Usando System.Convert no se pierden centavos, mientras que usando una conversión explícita de float a unint sí se pierde
            #region Ejemplo 10
            Separador.EscribirEncabezado("Ejemplo 10: Conversiones usando System.Convert");


            float amount  = 0.63f;
            uint  cents   = System.Convert.ToUInt16(amount * 100.0f);
            float dollars = cents / 100.0f;
            Console.WriteLine("Valor float inicial es de tipo float: {0}", amount.ToString());
            Console.WriteLine("Cents (uint convertido con System.Convert): {0}", cents.ToString());
            Console.WriteLine("Dollars (uint a float implícito) : {0}", dollars.ToString());

            cents   = (uint)(amount * 100.0f);
            dollars = cents / 100.0f;
            Console.WriteLine("Cents (conversión explicita a uint desde float): {0}", cents.ToString());
            Console.WriteLine("Dollars (conversión implícita desde uint a float usando el segundo valor de cents: {0}", dollars.ToString());

            Separador.EscribirPie("Fin Ejemplo 10");
            #endregion


            //Ejemplo 11: En este caso, es una definción de Cast entre dos clases creadas por mí.
            //Ver en Chapter7.Classes las definicones de OneMan y AnotherMan.
            //La conversión puede definrise en cualquiera de las dos clases (origen y target) con exactamente el mismo código,
            //y funcionará de las dos maneras
            #region Ejemplo 11
            Separador.EscribirEncabezado("Ejemplo 11: Conversiones personalizadas");

            OneMan unHombre = new OneMan("Juan Carlos", "Pelotudo");
            Console.WriteLine("El nombre de OneMan es: {0}, {1}", unHombre.LastName, unHombre.FirstName);
            AnotherMan otroHombre = (AnotherMan)unHombre;
            Console.WriteLine("El nombre completo de AnotherMan es: {0}", otroHombre.FullName);

            Separador.EscribirPie("Fin Ejemplo 11");
            #endregion



            //Ejemplo 12: En estos ejemplos se ve que el casteo de una clase derivada a una clase base no sirve de mucho
            //En ninguno de estos casos recupero el comportamiento de la clase base. Esto es porque el casting implícito
            //provisto por el compilador sólo cambia el tipo de referencia pero el objeto creado en Managed Heap es el mismo
            //Por eso siempre obtengo 4 divisores sin importar los pasajes que haga entre tipo derivado y tipo base
            //El único modo de obtener dos divisores es que el tipo base sea puro
            #region Ejemplo 12
            Separador.EscribirEncabezado("Ejemplo 12: Conversión entre clases");
            //Primer escenario: Casteo un EnteroPar para convertirlo en un Entero. Recibo el cast en una variable Entero
            EnteroPar dos       = new EnteroPar(3); //Aunque sea un contrasentido acá, sirve para los ejemplos de casteo con EnteroPrimo abajo para ver si tuvo éxito o no
            Entero    uno       = (Entero)dos;
            int[]     divisores = uno.Divisores();
            for (int i = 0; i < divisores.Length; i++)
            {
                Console.WriteLine("Divisores[{0}]={1}", i.ToString(), divisores[i].ToString());
            }

            //Segundo escenario: Declaro con el tipo base, pero uso el contructor del tipo derivado
            //Después casteo al tipo base recibiendo el cast en una variable del tipo base. Acá tengo dos escanrios distintos
            Entero cuatro       = new EnteroPar(4);
            Entero cinco        = (Entero)cuatro;
            int[]  DivisoresDe4 = cuatro.Divisores();
            for (int i = 0; i < DivisoresDe4.Length; i++)
            {
                Console.WriteLine("DivisoresDe4[{0}]={1}", i.ToString(), DivisoresDe4[i].ToString());
            }
            int[] DivisoresDe5 = cinco.Divisores();
            for (int i = 0; i < DivisoresDe5.Length; i++)
            {
                Console.WriteLine("DivisoresDe5[{0}]={1}", i.ToString(), DivisoresDe5[i].ToString());
            }


            //Aquí tengo un objeto puero de la clase base declarado y construido como de la clase base
            Entero entero6      = new Entero(6);
            int[]  DivisoresDe6 = entero6.Divisores();
            for (int i = 0; i < DivisoresDe6.Length; i++)
            {
                Console.WriteLine("DivisoresDe6[{0}]={1}", i.ToString(), DivisoresDe6[i].ToString());
            }

            //Ahora van escenarios entre EnteroPrimo y EnteroPar
            //Tomando el mismo objeto dos creado arriba
            EnteroPrimo tres         = (EnteroPrimo)dos;
            int[]       divisoresDe3 = tres.Divisores();
            for (int i = 0; i < divisoresDe3.Length; i++)
            {
                Console.WriteLine("divisoresDe3[{0}]={1}", i.ToString(), divisoresDe3[i].ToString());
            }

            //Y al revés, desde un primo genero un par
            EnteroPar seis         = (EnteroPar)tres;
            int[]     divisoresDe6 = seis.Divisores();

            for (int i = 0; i < divisoresDe6.Length; i++)
            {
                Console.WriteLine("divisoresDe6[{0}]={1}", i.ToString(), divisoresDe6[i].ToString());
            }

            Separador.EscribirPie("Fin ejemplo 12");
            #endregion



            //int i = 5;

            //if (i is object)
            //{
            //    Console.WriteLine(@"i is an object :)");
            //}
            //else
            //{
            //    Console.WriteLine(@"i is not an object :(");
            //}

            //Console.WriteLine("Un int necesita {0} bytes", sizeof(int).ToString());
            //Console.WriteLine("Un long necesita {0} bytes", sizeof(long).ToString());

            //int? a = null;
            //Nullable<int> b = null;
            //Console.WriteLine(b.HasValue);
            //b = a;

            //int entero = 5;
            //int? enteroNulo = null;
            //int enteroFinal = enteroNulo ?? entero;
            //Console.WriteLine("El valor de enteroFinal es {0}", enteroFinal.ToString());

            //long val = 30000000000;

            //try
            //{
            //    int otroVal = checked((int)val);
            //    Console.WriteLine("El valor de otroVal es: {0}", otroVal.ToString());
            //}
            //catch (Exception e)
            //{
            //    Console.WriteLine("Ocurrió una excepción de tipo {0}", e.ToString());

            //}

            //Person Curly = new Person();
            //Person Shemp = Curly;
            //bool test = ReferenceEquals(Shemp, Curly);
            //Console.WriteLine(test.ToString());
        }
Exemplo n.º 4
0
        static void Main(string[] args)
        {
            EncabezadoYPieConsola Separador = new EncabezadoYPieConsola();

            //Ejemplo 1: Creo una función, le apunto con un delegado
            //y luego llamo al delegado que es lo mismo que llamar a la función
            //Aquí uso Delegate Inference, la  línea 18 pudo haber sido: AStringFunction firstStringFunction = new AStringFunction(ThisFunction);
            #region Ejemplo 1

            Separador.EscribirEncabezado("Ejemplo 1: Ejemplo simple de Delegado");

            AStringFuntion firstStringFunction = ThisFunction;
            string         mensaje             = firstStringFunction();
            Console.WriteLine(mensaje);

            Separador.EscribirEncabezado("Fin Ejemplo 1");
            #endregion

            //Ejemplo 2: Usar un array de delegates
            #region Ejemplo 2
            Separador.EscribirEncabezado("Ejemplo 2: Array de Delegados");

            Operacion[] Operaciones =
            {
                new Operacion(MathOperations.MultiplicarPorDos),
                new Operacion(MathOperations.Cuadrado)
            };

            for (int i = 0; i < Operaciones.Length; i++)
            {
                CalcularYMostrar(Operaciones[i]);
            }

            Separador.EscribirPie("Fin Ejemplo 2");
            #endregion


            //Ejemplo 3: Lo mismo que en ejemplo 2, pero usando un Generic Delegate
            //Vemos que no hace falta declarar el delegado específico, porque uso la declaración Genérica que ya está provista por C#
            #region Ejemplo 3
            Separador.EscribirEncabezado("Ejemplo 3: Generic Delegate");

            Func <int, long>[] OperacionesConGeneric =
            {
                MathOperations.MultiplicarPorDos, MathOperations.Cuadrado
            };
            for (int i = 0; i < OperacionesConGeneric.Length; i++)
            {
                CalcularConGenericYMostrar(OperacionesConGeneric[i]);
            }

            Separador.EscribirPie("Fin Ejemplo 3");
            #endregion


            //Ejemplo 4: Aquí veo el poder real de los Generics y de los Delegate.
            #region Ejemplo 4
            Separador.EscribirEncabezado("Ejemplo 4: Bubblesorter");
            //En el primer caso ordeno un array de enteros usando un BubbleSorter que está definido
            //sólo para el caso en que tenga que ordenar enteros, es una implementación específica
            //Ordenar un array de enteros
            int[] array = PrepareArray();
            Console.WriteLine("Array antes de ordenar");
            PrintArray(array);
            BubbleSorter.BubbleSort(array);
            Console.WriteLine("Array después de ordenar");
            PrintArray(array);

            //Ahora, voy a ordenar una lista de objetos definidos por mí
            //En este caso, la definición del BubbleSorter no está atada a la clase sino que es completamente genérica

            //Ordenar una List de Employees
            List <Employee> empleados = PrepareEmployees();
            Console.WriteLine("Lista de Empleados antes de ordenar");
            PrintEmployees(empleados);
            BubbleSorter.GenericBubbleSort(empleados, Employee.CompareTo);
            Console.WriteLine("Lista de Empleados después de ordenar");
            PrintEmployees(empleados);


            //Ordenar un Array de Employees
            //Como el BubbleSorter tiene un parámetro de tipo
            //IList<T> en List<T> puedo usar también un array
            Employee[] arrayDeEmpleados = PrepareEmployeeArray();
            Console.WriteLine("Array de Empleados antes de ordenar");
            PrintEmployees(arrayDeEmpleados);
            BubbleSorter.GenericBubbleSort(arrayDeEmpleados, Employee.CompareTo);
            Console.WriteLine("Array de Empleados después de ordenar");
            PrintEmployees(arrayDeEmpleados);

            Separador.EscribirPie("Fin de Ejemplo 4");
            #endregion


            //Ejemplo 5: Multicast Delegate
            //Como se ve, no hay necesidad de declarar el Multicast Delegate ya que uso el Generic Delegate Action<T>
            //Y con una sola llamada se invocan todas las funciones de la lista
            #region Eejemplo 5
            Separador.EscribirEncabezado("Ejemplo 5: Multicast Delegate");

            Action <int> OperacionesNulas = MathOperations.CuadradoYMostrar;
            OperacionesNulas += MathOperations.Dividir5PorX;
            OperacionesNulas += MathOperations.MutiplicarPorDosyMostrar;
            OperacionesNulas(2);
            OperacionesNulas(500);
            //El problema potencial es que si llega a fallar algo en el medio (una excepción en alguna invocación)
            //pueden no invocarse todas las funciones. Para eso uso la enumeración con un try catch
            Delegate[] OperacionesPorLista = OperacionesNulas.GetInvocationList();
            foreach (Action <int> accion in OperacionesPorLista)
            {
                accion(7);

                try
                {
                    accion(0);
                }
                catch (Exception e)
                {
                    ReportarExcepcion(e);
                }

                accion(1000);
            }

            Separador.EscribirPie("Fin Ejemplo 5");
            #endregion


            //Ejemplo 6: Anonymous Delegate
            //Recordemos todas las instancias de definción de delegados
            //Primero la más explícita y verbosa:
            //delegate string GetAstring();
            //int x = 5;
            //GetAstring StringDeEntero = new GetAString(x.toString());
            //****
            //Despsués le saqueé la llamada explícita al constructor con Inferencia. Reemplazo la última línea por:
            //GetAString StringDentero = x.ToString();
            //Después usé Generics para no tener que declarar (me libro de la primera línea de arriba):
            //Func<string> StringDeEntero = x.ToString():
            //Y ahora finalmente uso método anónimo:
            //Func<string> StringDeEntero = delegate()
            //{
            //  return x.ToString();
            //}
            //Incluso puedo usar la variable x declarada fuera del Delegate
            #region Ejemplo 6
            //Usar Anonymous Delegate
            Func <int, int> anonDel = delegate(int param)
            {
                param += 10;
                return(param);
            };
            Console.WriteLine("El valor retornado usando un Anonymous Delagate es: {0}", anonDel(50));

            //Usar Lambda Expression - Ejemplo simple
            Func <int, int> lambda = param =>
            {
                param += 10;
                return(param);
            };
            Console.WriteLine("El valor retornado usando una Lambda Expression es: {0}", lambda(50));
            #endregion

            //Ejemplo 6: Lambda Expression
            #region Ejemplo 7
            //Usar Lambda expression inline
            Func <int, int> LambdaSingle = param => param += 10;
            Console.WriteLine("El valor retornado usando una Single Line Lambda es: {0}", LambdaSingle(50));
            #endregion
        }