Sistema de numeración en base primorial

Sistema de numeración en base primorial

En mi otro blog, hace poco estuve hablando de un sistema de posicionamiento mixto como era el sistema de numeración en base primorial, el cual varía en cada posición la base, bueno pues he creado una estructura en la cual se incluye además de la conversión, los operadores de suma, resta, multiplicación y división y los de comparación. Es una estructura sencilla en la que no me he esmerado mucho, pero espero que quede claro el uso de estructuras, interfaces y sobrescritura de operadores. Lo primero de todo, ¿por que una estructura y no una clase?. Antes de nada vamos a enumerar las características de las estructuras:

  • Una estructura hereda de la clase abstracta System.ValueType y esta a su vez de object
  • Una estructura no permite la herencia, solo pueden implementar interfaces
  • Una estructura no puede ser abstracta
  • No permite un constructor sin parámetros y no puede tener destructor.
  • Si contiene campos o propiedades, tienen que ser asignados en el constructor
  • Las variables no pueden ser inicializadas fuera del constructor
  • Es posible crear una estructura sin usar el operador new, en tal caso, no es posible usar la estructura hasta que todos los campos se inicialicen.

¿Para que se utilizan? Para representar objetos de poca monta que no tengan grandes cálculos (también podríamos hacerlo con una clase), pero lo primero, nos aseguramos que se han inicializado todas las variables y campos y en el caso de tener un constructor, contiene un parámetro de entrada como mínimo, además no es necesario instanciar la estructura mediante new. El típico ejemplo de una estructura sería un sistema de coordenadas, como podemos ver en el ejemplo, se asignan los valores en el constructor y podemos tener

    public struct Cooordenadas3D
    {
        public int x, y, z;

        public Cooordenadas3D(int _x, int _y, int _z)
        {
            x = _x;
            y = _y;
            z = _z;
        }

        public override string ToString()
        {
            return "(" + x + ", " + y + ", " + z + ")";
        }

        public double GetModulo()
        {
            //.... return ...
        }
        public double GetAngulo()
        {
            //.... return ...
        }

Y yo con mi sistema de numeración en base primorial lo he hecho, he implementado el sistema mediante una estructura y que vamos a detallar con detenimiento.

Lo primero, hemos dicho que no puede heredar de ninguna clase, pero si puede implementar interfaces. Yo implemento las interfaces IComparable, IComparable<PrimorialBaseNumber>, IEquatable<PrimorialBaseNumber>. La primera y la segunda implementan el método CompareTo que nos hará falta para los operadores y la tercera, que implementa el método Equals que nos hará falta también para los operadores.

He acotado el código en regiones y dentro de estas, explico que hay:

  • Constructor (contructor). En el constructor, le pasamos como parámetro el número decimal que queremos convertir a nuestro sistema y dentro de este inicializamos el array de los primero 45 números primos y ¿por qué 45? esta lista se usará para generar el primorial y el primorial 45 o lo que es lo mismo 199# equivale a 7.7999220416834615532491991063298e+81 que para este ejemplo creo que va bien, al mismo tiempo, este número tan grande, lo he usado como valor máximo del sistema, (por acotar)
  • Constants (constantes). He declarado cinco constantes, de la cuales realmente solo usamos dos, el valor máximo y mínimo (el resto las tengo de otras estructuras y clases y las he dejado). como he comentado, el valor máximo y mínimo, es el valor del primorial de 199 (199#)
  • Properties and Fields (Campos y propiedades). Un array estática con los 45 primeros números primos, un propiedad para almacenar el valor en decimal (DecimalValue) y otra el valor en base primorial (Value). Dentro de la propiedad DecimalValue, se calcula el valor de Value, de modo que si cambiamos el valor del primero, se calcula el del segundo.
  • Public Methods (Métodos públicos).
    • Comparisons (comparaciones). En esta región entran los métodos CompareTo de objeto y del tipo PrimorialBaseNumber, obligatoriamente implementados ya que la interface IComparable, IComparable así lo marcan. Estos devuelven 1 si es mayor, 0 si es igual y -1 si es menor y el método Equals por la interfaz IEquatable<PrimorialBaseNumber>; esta devuelve true si los dos objetos son iguales.
    • Conversions (conversiones). En esta región, tres métodos y uno de ellos sobrecargado. ToString() que devuelve el valor en base primorial, ToDecimal() que devuelve el valor en base decimal y ToPrimorialBase()ToPrimorialBase(decimal _number), el primero hace lo mismo que ToString() pero devuelve un valor tipo decimal y el segundo asigna el valor en base decimal a DecimalValue y en consecuencia lo convierte y devuelve el número convertido.
    • Operators (operadores). Un ejemplo de sobrecarga de los operadores lo expuse en el post de calculadora de números complejos, en el que si yo sumo el objeto complex con otro complex, el compilador no sabe como ejecutar el cálculo, mientras que si sobrecargamos el método, podemos decirle como efectuar esa operación y cada vez que se use, así lo hará. He sobrecargado todos los operadores posibles, para hacerlo lo más genérico posible. Para realizar las operaciones podría haber usado un método más elemental matemáticamente hablando, sumando dígito a dígito, acarreos, etc., pero lo he hecho con las operaciones en base decimal, es más fácil, ¿no?.
    • Static (Estáticos). En esta región incluyo la obtención del primorial mediante un método estático, el cual puede ser accesible desde fuera y dentro de la estructura.
  • Private methods (métodos privados). aquí iría el motor de la estructura, que para el usuario debe estar oculto (tu no ves en tu coche los pistones moverse o las explosiones en los cilindros, ¿verdad?), donde se calculan las conversiones a base decimal, a base primorial.

y ahora el código

/* ************************************************************************************
* © JOAQUIN MARTINEZ RUS 2016
* PROYECTO:         PrimorialBaseNumber
* Nombre:           Mersenne
* Archivo:          PrimorialBaseNumber.cs
* Descripción:      Estructura de un sistema de numeración mixto primorial
* Historial:
*                   1. Joaquin Martínez Rus - 19 ago 2016. Creación
*
* Comentarios:      Contempla la conversión de números en base decimal a base primorial y viceversa,
*                   así como los operadores de suma, resta, multiplicación, división, resto, igualdad,
*                   distinto, complemento y comparativos
*
*
************************************************************************************/
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System
{
    public struct PrimorialBaseNumber : IComparable, IComparable, IEquatable
    {
        #region Constructor

        public PrimorialBaseNumber(decimal _DecimalNumber)
        {
            // Inicializando todas las propiedades y variables
            PrimorialBaseNumber.primeNumber = new decimal[] {
                2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                31, 37, 43, 47, 53, 59, 61, 67, 71, 73,
                79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
                131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
                181, 191, 193, 197, 199 };
            Value = 0;
            _decimalValue = 0;
            DecimalValue = _DecimalNumber;

        }

        #endregion

        #region Constants

        public const double MaxValue = 7.7999220416834615532491991063298e+81; // 199#
        public const double MinValue = -7.7999220416834615532491991063298e+81;
        public const double NaN = 0D / 0D;
        public const double NegativeInfinity = -1D / 0D;
        public const double PositiveInfinity = 1D / 0D;

        #endregion

        #region Properties and Fields

        private decimal _decimalValue;

        public decimal DecimalValue
        {
            get { return _decimalValue; }
            set
            {
                _decimalValue = value;
                Value= ConvertToPrimorialBaseNumber(_decimalValue);
            }
        }

        public decimal Value { get; set; }

        public static decimal[] primeNumber { get; set; }

        #endregion

        #region Public Methods

        #region Comparisons

        /// <summary>
        /// Compara esta instancia con un objeto específico y retorna un entero que indica
        /// si el valor es menor que, igual a o mayor que el valor de objeto específico
        /// </summary>

        /// Objeto a comparar a null
        /// Retorna un entero con signo. Negativo si es menor, un 0 si es igual y un entero positivo si es mayor.
        /// Si el valor es null, retorna error
        public int CompareTo(object obj)
        {
            try
            {
                if (obj == null) throw new ArgumentNullException();

                return CompareTo((PrimorialBaseNumber)obj);
            }
            catch (Exception)
            {
                throw new FormatException("Error en la conversión del tipo Object al tipo PrimorialBaseNumber");
            }
        }

        /// <summary>
        /// Compara esta instancia con un objeto específico y retorna un entero que indica
        /// si el valor es menor que, igual a o mayor que el valor de objeto específico
        /// </summary>

        /// Objeto a comparar a null
        /// Retorna un entero con signo. Negativo si es menor, un 0 si es igual y un entero positivo si es mayor.
        /// Si el valor es null, se devuelve NaN
        public int CompareTo(PrimorialBaseNumber obj)
        {
            int value = 0;

            if (DecimalValue &gt; obj.DecimalValue)
            {
                value = 1;
            }
            else if (DecimalValue &lt; obj.DecimalValue)
            {
                value = -1;
            }

            return value;
        }

        /// <summary>
        /// Retorna un valor que indica si esta instancia es igual a un PrimorialBaseNumber específico
        /// </summary>

        /// Un objeto PrimorialBaseNumber a comparar con esta instancia
        /// True si tiene el mismo valor que esta instancia
        public bool Equals(PrimorialBaseNumber other)
        {
            try
            {
                return this == other;
            }
            catch (Exception)
            {

                throw new FormatException();
            }

        }

        /// <summary>
        /// Retorna un valor que indica que esta instancia es igual a un objeto específico
        /// </summary>

        /// Un objeto a comparar con esta instancia
        /// True si es una instancia del tipo PrimorialBaseNumber y tiene el mismo valor que esta instancia
        public override bool Equals(Object other)
        {
            try
            {
                return Equals((PrimorialBaseNumber)other);
            }
            catch (Exception)
            {
                throw new FormatException("Error en la conversión del tipo Object al tipo PrimorialBaseNumber");
            }
        }

        #endregion

        #region Conversions

        /// <summary>
        /// Convierte el valor numérico de esta instancia a su equivalente string
        /// </summary>

        /// El equivalente a string de esta instancia
        public override string ToString()
        {
            return Value.ToString();
        }

        /// <summary>
        /// Obtiene el valor numérico en base decimal
        /// </summary>

        /// El equivalente al número en base decimal
        public decimal ToDecimal()
        {
            return DecimalValue;
        }

        /// <summary>
        /// Obtiene el valor numérico en base primorial
        /// </summary>

        /// El equivalente al número en base primorial
        public decimal ToPrimorialBase()
        {
            return Value;
        }

        /// <summary>
        /// Convierte el número del parámetro en base decimal a base primorial y
        /// retorna el número convertido asignándolo al valor de esta instancia
        /// </summary>

        /// Número en base decimal que se va a convertir a base primorial
        /// Número en base primorial
        public decimal ToPrimorialBase(decimal _number)
        {
            DecimalValue = _number;
            return Value;
        }

        #endregion        

        #region Operators

        /// <summary>
        /// Retorna un valor que indica la suma de ambos términos
        /// </summary>

        /// Primer valor de la suma
        /// Segundo valor de la suma
        /// Valor de la suma de ambos términos en base Primorial
        public static PrimorialBaseNumber operator + (PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            decimal value = left.DecimalValue + right.DecimalValue;

            if ((double)value &gt; MaxValue || (double)value &lt; MinValue)
            {
                throw new OverflowException(&quot;El valor de la suma es superior o inferior al valor máximo o mínimo respectivamente de la instancia&quot;);
            }
            return new PrimorialBaseNumber(value);
        }

        /// <summary>
        /// Retorna un valor que indica la resta de ambos términos
        /// </summary>

        /// Primer valor de la resta
        /// Segundo valor de la resta
        /// Valor de la resta de ambos términos en base Primorial
        public static PrimorialBaseNumber operator -(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            decimal value = left.ConvertToDecimal() - right.ConvertToDecimal();

            if ((double)value &gt; MaxValue || (double)value &lt; MinValue)
            {
                throw new OverflowException(&quot;El valor de la resta es superior o inferior al valor máximo o mínimo respectivamente de la instancia&quot;);
            }
            return new PrimorialBaseNumber(value);
        }

        /// <summary>
        /// Retorna un valor que indica el producto de ambos términos
        /// </summary>

        /// Primer valor del producto
        /// Segundo valor del producto
        /// Valor del producto de ambos términos en base Primorial
        public static PrimorialBaseNumber operator * (PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            decimal value = left.ConvertToDecimal() * right.ConvertToDecimal();

            if ((double)value &gt; MaxValue || (double)value &lt; MinValue)
            {
                throw new OverflowException(&quot;El valor del producto es superior o inferior al valor máximo o mínimo respectivamente de la instancia&quot;);
            }
            return new PrimorialBaseNumber(value);
        }

        /// <summary>
        /// Retorna un valor que indica la división de ambos términos
        /// </summary>

        /// Primer valor de la división
        /// Segundo valor de la división
        /// Valor de la división de ambos términos en base Primorial
        public static PrimorialBaseNumber operator / (PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            if (right.ConvertToDecimal()==0)
            {
                throw new DivideByZeroException();
            }

            decimal value = left.ConvertToDecimal() / right.ConvertToDecimal();

            if ((double)value &gt; MaxValue || (double)value &lt; MinValue)
            {
                throw new OverflowException(&quot;El valor de la división es superior o inferior al valor máximo o mínimo respectivamente de la instancia&quot;);
            }
            return new PrimorialBaseNumber(value);
        }

        /// <summary>
        /// Retorna un valor que indica el resto de la división de ambos términos
        /// </summary>

        /// Primer valor de la operación resto
        /// Segundo valor de la operación resto
        /// Valor del resto de la división de ambos términos en base Primorial
        public static PrimorialBaseNumber operator % (PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            decimal value = left.DecimalValue % right.DecimalValue;
            return new PrimorialBaseNumber(value);
        }

        /// <summary>
        /// Retorna un valor que indica el complemento de esta instancia
        /// </summary>

        /// Valor del número al que se le calcula el complemento
        /// Valor del complemento del número
        public static PrimorialBaseNumber operator !(PrimorialBaseNumber _number)
        {
            int index = 0;
            decimal primorial = 1;
            decimal complemento = 0;
            // Buscar el primer primorial que sea mayor que el número
            do
            {
                primorial = GetPrimorial(index);
                index++;
            } while (primorial &lt; _number.DecimalValue);

            complemento = primorial - _number.DecimalValue;

            return new PrimorialBaseNumber(complemento);
        }

        /// <summary>
        /// Retorna un valor que indica que ambos valores son iguales
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación&lt;
        /// Verdadero si el valor de la izquierda y el de la derecha son iguales; en otro caso, retorna false
        public static bool operator ==(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            bool isEqual = true;

            if (left.ToString().Length!= right.ToString().Length)
            {
                isEqual = false;
            }
            for (int i = 0; i &lt; left.ToString().Length; i++)
            {
                if (left.ToString()[i]!=right.ToString()[i])
                {
                    isEqual = false;
                    break;
                }
            }

            return isEqual;
        }

        /// <summary>
        /// Retorna un valor que indica que ambos valores no son iguales
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación
        /// Verdadero si el valor de la izquierda y el de la derecha no son iguales; en otro caso, retorna false
        public static bool operator !=(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            return !(left==right);
        }

        /// <summary>
        /// Retorna un valor que indica que un valor específico es menor que otro
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación
        /// Verdadero si el valor de la izquierda es menor que el de la derecha; en otro caso, retorna false
        public static bool operator &lt;(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            if (left.CompareTo(right) ==-1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Retorna un valor que indica que un valor específico es mayor que otro
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación
        /// Verdadero si el valor de la izquierda es mayor que el de la derecha; en otro caso, retorna false
        public static bool operator &gt;(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            if (left.CompareTo(right) == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Retorna un valor que indica que un valor específico es menor o igual que otro
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación
        /// Verdadero si el valor de la izquierda es menor o igual que el de la derecha; en otro caso, retorna false
        public static bool operator &lt;=(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            if (left.CompareTo(right) == -1 || left.CompareTo(right)==0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Retorna un valor que indica que un valor específico es mayor o igual que otro
        /// </summary>

        /// Primer valor de la comparación
        /// Segundo valor de la comparación
        /// Verdadero si el valor de la izquierda es mayor o igual que el de la derecha; en otro caso, retorna false
        public static bool operator &gt;=(PrimorialBaseNumber left, PrimorialBaseNumber right)
        {
            if (left.CompareTo(right) == 1 || left.CompareTo(right) == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region Static

        /// <summary>
        /// Retorna el valor del primorial de n
        /// </summary>

        /// Valor de n en el conjunto de los números primos
        /// Retorna el valor correspondiente al primorial de n
        public static decimal GetPrimorial(int n)
        {

            if (n &gt; primeNumber.Length)
            {
                throw new OverflowException();
            }

            decimal result = 1;

            for (int i = 0; i &lt; n; i++)
            {
                Decimal prime = primeNumber[i];
                result *= prime;
            }
            return result;
        }

        #endregion

        #endregion

        #region Private Methods

        /// <summary>
        /// Convierte un número en base decimal a base primorial
        /// </summary>

        /// Número que se va a convertir
        /// Valor decimal del número en base primorial
        private decimal ConvertToDecimal(decimal _number)
        {
            IEnumerable arrayToString = _number.ToString().ToCharArray().Reverse();
            Decimal result = 0;
            int contador = 0;
            foreach (var item in arrayToString)
            {
                Decimal primorial = GetPrimorial(contador++);
                int digit = Convert.ToInt32(item.ToString());
                result += digit * primorial;

            }
            return result;
        }

        /// <summary>
        /// Convierte el valor en base decimal de esta instancia a base primorial
        /// y lo asigna al valor en base primorial de esta instancia
        /// </summary>

        /// Valor decimal del número en base primorial
        private decimal ConvertToDecimal()
        {
            return ConvertToDecimal(Value);
        }

        /// <summary>
        /// Convierte un número decimal en base 10 a base primorial
        /// </summary>

        /// Número a convertir
        /// Número en base primorial
        private decimal ConvertToPrimorialBaseNumber(decimal _number)
        {
            StringBuilder result = new StringBuilder();
            decimal dividendo = _number;
            decimal resto = 0;

            int index = 0;

            do
            {
                resto = dividendo % primeNumber[index];
                dividendo = Math.Truncate(dividendo / primeNumber[index]);
                result.Insert(0, resto);
                index++;
            } while (dividendo &gt; 0);

            return Convert.ToDecimal(result.ToString());
        }

        #endregion

    }
}

y para ver como funciona, o creáis un formulario y le añadis la estructura o creáis una aplicación de consola y hacéis lo mismo. Yo he creado un formulario, le he añadido un textbox y le he ido añadiendo los calculos para ver que funciona

            // Iniciando estructuras
            PrimorialBaseNumber pbnn1 = new PrimorialBaseNumber(907);
            PrimorialBaseNumber pbnn2 = new PrimorialBaseNumber(487);            

            textBox.AppendText("487=> " + pbnn1.ToPrimorialBase(487) + "\n");
            textBox.AppendText("907=> " + pbnn1.ToPrimorialBase(907) + "\n");

            textBox.AppendText("suma 487+907 => " + (pbnn1 + pbnn2) + "\n");
            textBox.AppendText("resta 907-487 => " + (pbnn1 - pbnn2) + "\n");
            textBox.AppendText("multi 487*907 =>" + (pbnn1 * pbnn2) + "\n");
            textBox.AppendText("!1544=> " + (2310-1544) + "\n");
            pbnn1.ToPrimorialBase(1544);
            textBox.AppendText("!1544=> " + !pbnn1 + "\n");
            textBox.AppendText("766=> " + !pbnn1 + "\n");

y este el resultado

487=> 22101
907=> 42101
suma 487+907 => 64210
resta 907-487 => 20000
multi 487*907 => 14922301
!1544=> 766
!1544=> 34220
766=> 34220

como siempre, comentad el código y mantenedlo organizado y si tenéis alguna pregunta, no dudéis en dejar un comentario

saludos

Pd: Repito, esta estructura está realizada en una tarde, por lo que entiendo que es muy mejorable y debe abarcar todos las cotas y aspectos, pero para aprender , a mi parecer, está bien, además como mejor se aprende, es picando código!

14.- Instrucciones de Salto

14.- Instrucciones de Salto
Hola a todos de nuevo. Hoy vamos a estudiar las instrucciones de salto. ¿Y que son las instrucciones de salto? Todos sabemos que en un programa las instrucciones se ejecutan secuencialmente, pues estas, nos permiten saltar de una parte del programa a otro evitando esa ejecución secuencial.Las instrucciones de salto para C# son:

  • break
  • continue
  • goto
  • return
  • throw

Y para VB.NET

  • Exit For
  • Exit Do
  • Exit While
  • Exit Select
  • Continue For
  • goto
  • Return

Paso a paso, vamos a detallar una por una excepto la última que la incluiremos en el tratamiento de errores.

La instrucción break nos permita terminar un bucle o salir de una instrucción switch, es decir por ejemplo, si creamos un bucle do while que vaya sumando 1 a una variable y le ponemos la condición de que cuando esa variable llegue a 100 salga del bucle, pues en la parte verdadera de esa condición es donde debemos poner el break, para que así salga y no siga sumando. Para VB.NET, se utiliza Exit For para un bucle For Next, Exit Do para un bucle Do While, Exit While para un bucle While y Exit Select para una instrucción Select Case. Como veis, C# se complica menos y utiliza break para todos los casos.

for (int i = 1; i <= 1000; i++)
{
	if (i == 100)
	{
		break;
	}
	Console.WriteLine(i);
}

Mismo caso pero con una instrucción while

int n = 0;
while (true)
{
	n += 1;
	if (n==100)
	{
		break;
	}
}

Y su equivalente para Vb.NET

        For i As Integer = 1 To 1000
            If i = 100 Then
                Exit For
            End If
            Console.WriteLine(i)
        Next
        Dim n As Integer = 0
        While True
            n += 1
            If n = 100 Then
                Exit While
            End If
        End While

continue, es una instrucción que no suelo utilizar a menudo, pero es curiosa en cuanto a su funcionamiento. Esta lo que provoca dentro de un bucle for o foreach, pasar a la siguiente iteración, por ejemplo.

            for (int i = 1; i <= 10; i++)
            {
                if (i < 9)
                {
                    continue;
                }
                Console.WriteLine(i);
            }

En este ejemplo cuando i es menor que 9 la instrucción continue evita que se escriba en la consola pasando a darle un valor nuevo a i hasta que i es mayor o igual a 9, donde entonces se imprimirá el valor en pantalla. Su equivalente en VB.NET es Continue For.

        For i As Integer = 1 To 10
            If i < 9 Then
                Continue For
            End If
            Console.WriteLine(i)
        Next

Goto transfiera o envía el control del programa a un sitio concreto del programa y ¿cómo sabe donde tiene que enviarlo?, pues porque en ese lugar debe existir una etiqueta. También puede usarse para transferir el control de programa a una etiqueta de una instrucción switch. Además, como es normal, podemos usarla también para salir de bucles, ¿no crees? Exponemos ejemplos. En el primero, aparecerá en pantalla ‘He salido’ cuando el valor de i valga 9.

C#

            for (int i = 1; i <= 10; i++)
            {
                if (i > 8)
                {
                    goto SalidaPrograma;
                }
            }
        SalidaPrograma:
            Console.WriteLine("He salido");

VB.NET


        For i As Integer = 1 To 10
            If i > 8 Then
                GoTo SalidaPrograma
            End If
        Next
SalidaPrograma:
        Console.WriteLine("He salido")

En el caso de salto dentro de una instrucción switch, lo vemos a continuación en el que dependiendo del valor de n, (el resto no me valen), en el que para el caso de 2 y 3, efectuará la suma propia del caso, pero además lo reenviará al valor 1 donde volverá a sumarle 25, ¿ok?
C#

            int valor=0;
            switch (n)
            {
                case 1:
                    valor += 25;
                    break;
                case 2:
                    valor += 25;
                    goto case 1;
                case 3:
                    valor += 50;
                    goto case 1;
                default:
                    Console.WriteLine("Esto no me vale");
                    break;
            }

VB.NET


        Dim valor As Integer = 0
        Select Case n
            Case 1
                valor += 25
                Exit Select
            Case 2
                valor += 25
             goto case 1
            Case 3
                valor += 50
             goto case 1
            Case Else
                Console.WriteLine("Esto no me vale")
                Exit Select
        End Select

La instrucción return acaba la ejecución del método donde se ha ejecutado y devuelve el control al método que llamó antes, además puede devolver algún valor. Con un ejemplo lo veremos con más claridad.

Si ejecutamos el método Inicio, se llamará al método CalcularAreaCirculo con un valor de radio igual a 5. Dentro del método de cálculo, se efectuarán los cálculos pertinentes para obtener el área y acto seguido se ejecuta return area, devolviendo el valor del área al método que lo llamó que es Inicio. Una vez este tiene el valor, lo visualiza en pantalla. Lo que si tenemos que tener en cuenta para VB.NET, es que para que un método devuelva un valor, debe ser una función (Function), cosa que en C# en vez de void se le asigna un tipo.

C#

            private void Inicio()
            {
                int radius = 5;
                double result = CalcularAreaCirculo(radius);
                Console.WriteLine("El area es {0:0.00}", result);
                Console.ReadKey();
            } 

            private double CalcularAreaCirculo(int r)
            {
                double area = r * r * Math.PI;
                return area;
            }

VB.NET

    Private Sub Inicio()
        Dim radius As Integer = 5
        Dim result As Double = CalcularAreaCirculo(radius)
        Console.WriteLine("El area es {0:0.00}", result)
        Console.ReadKey()
    End Sub

    Private Function CalcularAreaCirculo(r As Integer) As Double
        Dim area As Double = r * r * Math.PI
        Return area
    End Function

Pues esto es todo en cuanto a las instrucciones de salto, fácil, ¿no?. Pues nos vemos en la próxima entrega!!

Saludos “der Waki”

13.- Instrucciones de iteración

13.- Instrucciones de iteración

Por fin he vuelto. Estimados amigos, he tenido que dejar por una temporada el blog de Aprender a programar para mejorar mis conocimientos anglo-lingüísticos y me han absorbido todo el tiempo del mundo, pero a partir de ahora… si nada ni nadie lo impide, seguiremos en primera línea. Vamos allá.Bueno pues las instrucciones de iteración nos permiten repetir ciertas acciones o crear un bucle. Un bucle se puede repetir un número de veces limitado porque aunque se puede hacer ilimitado no tiene ningún sentido crear un programa que no acabe nunca, ¿no?. Dentro de estos bucles se ejecutan las instrucciones ordenadamente salvo cuando utilizamos otro tipo de instrucciones que son las de salto.

Tenemos varios tipos de instrucciones de salto y la primera de todas es do-while (hacer mientras…). Ahora vamos a ver un ejemplo para C# y su equivalente para VB .NET. Esta instrucción ejecuta un bloque de instrucciones repetidas veces hasta que una determinada instrucción se evalúa como false. Para C# el bloque de código se incluye entre llaves y acto seguido se incluye la expresión booleana. En el siguiente ejemplo creamos una pequeña aplicación que imprimirá por pantalla los valores desde 0 a 2. Como veis, al entrar en el bucle, se imprime el primer valor de x que es cero, después le suma a x una unidad (x++ esto de verdad que suma una unidad, es un operador y lo veremos en un futuro) , efectúa la comprobación x vale ahora 1, ¿1 es menor que 3?, si (true), pues volvemos al inicio del bucle do y se vuelve a ejecutar el mismo código hasta que x llega a tener el valor de 3 que en ese caso 3 no es menor que 3 y la expresión booleana sería false. En este momento, saldría del bucle. Para VB.NET es igual pero con Do y Loop While donde el contenido de código incluido entre ambas instrucciones, es lo que se ejecutará mientras la expresión While sea false. El aspecto fundamental de esta instrucción es que por lo menos, el bloque de código se ejecuta una sola vez ya que una vez ejecutado es cuando se comprueba la expresión booleana que permitirá seguir ejecutando este o salir del bucle.

C#

public class DoWhile_Prueba
    {
        public static void Main()
        {
            int x = 0;
            Console.WriteLine("SALIDA EN PANTALLA");
            do
            {
                Console.WriteLine(x);
                x++;
            } while (x &lt; 3);
            Console.WriteLine("FIN DE BUCLE");
        }
    }
    /* SALIDA EN PANTALLA:
      	0
        1
        2
    */

Vb.NET

Public Class DoWhile_Prueba
    Public Shared Sub Main()
        Dim x As Integer = 0
        Console.WriteLine("SALIDA EN PANTALLA")
        Do
            Console.WriteLine(x)
            x += 1
        Loop While x &lt; 3
        Console.WriteLine("FIN DE BUCLE")
    End Sub
End Class
'
'        SALIDA EN PANTALLA:
'        0
'        1
'        2

Ahora vamos a ver la instrucción while y su equivalente en VB.NET While y End While. En este tipo de instrucciones, la expresión booleana se verifica al principio, por tanto si al comienzo no se verifica la expresión , no se ejecutará ni una sola vez el contenido de código del bucle (esta es la principal diferencia con Do-While). Con esta instrucción, he incluido un cosita nueva, en la anterior instrucción metimos un operador de adición y en esta un parámetro. Cuando le damos formato a un texto como es en el siguiente caso, una vez vale una cosa y a la siguiente vale otra, bueno pues utilizamos unas llaves con un número en su interior y cuando se ejecute, se buscará por orden el primer parámetro disponible. Un ejemplo y lo entenderéis.

Console.WriteLine("Hola {0} {0}, me llamo {1} {2}, y esto es una {3}", "amigos", "Joaquín", "Martínez", "prueba");

{0} equivale a amigos, {1} a Joaquín, {2} a Martínez y {3} a prueba.
Esto imprimirá en pantalla “Hola amigos amigos, me llamo Joaquín Martínez y esto es una prueba”. Si os dais cuenta en cada hueco donde antes existía una llave y un número, ahora existe su equivalente en texto con el mismo orden en el que encontraba. Aunque no lo parezca, esto es muy útil!

C#

class WhileTest_Prueba
    {
        static void Main()
        {
     Console.WriteLine("Salida en pantalla")
            int n = 1;
            while (n < 6)
            {
                Console.WriteLine("Valor actual de n es {0}", n);
                n++;
            }
        }
    }
    /* Salida en pantalla:
        Valor actual de n es 1
        Valor actual de n es 2
        Valor actual de n es 3
        Valor actual de n es 4
        Valor actual de n es 5
     */

VB.NET

Class WhileTest_Prueba
    Private Shared Sub Main()
        Dim n As Integer = 1
        Console.WriteLine("Salida en pantalla")
        While n < 6
            Console.WriteLine("Valor actual de n es {0}", n)
            n += 1
        End While
    End Sub
End Class
'
'        Salida en pantalla:
'        Valor actual de n es 1
'        Valor actual de n es 2
'        Valor actual de n es 3
'        Valor actual de n es 4
'        Valor actual de n es 5

Ojo con este tipo de instrucciones porque SIEMPRE deben tener una salida, es decir que alguna vez se debe cumplir el valor de la expresión en false para poder salir del bucle, porque si no se convertiría en un bucle infinito sin ninguna utilidad. En el siguiente ejemplo ocurriría esto. Ya que el valor de nes 4 y la instrucción se ejecutará mientras que n sea mayor que 3, por tanto entraría en un bucle sin fin. Otra forma de salir de un bucle es mediante break, goto o return para C# o Exit While o Exit For, GoTo o Return.

C#

class WhileTest_Prueba
    {
        static void Main()
        {
            int n = 4;
            while (n > 3)
            {
                Console.WriteLine("Valor actual de n is {0}", n);
                n++;
            }
        }
    }

VB.NET

Class WhileTest_Prueba
    Private Shared Sub Main()
        Dim n As Integer = 1
        Console.WriteLine("Salida en pantalla")
        While n < 6
            Console.WriteLine("Valor actual de n is {0}", n)
            n += 1
            Return
        End While
    End Sub
End Class
'
'        Output:
'        Valor actual de n es 1
'        Valor actual de n es 2
'        Valor actual de n es 3
'        Valor actual de n es 4
'        Valor actual de n es 5

Otra instrucción de iteración, for para C# y For Next para VB.NET. Estas se ejecutan n-veces hasta que una expresión sea false y son muy útiles para recorrer matrices o para casos en los que conocemos el número de veces que se va a repetir un bucle. Por ejemplo vamos a ejecutar una instrucción 5 veces. La instrucción for realiza varias funciones. El primero y solo se hace una vez es declarar un variable i asignándole el valor de 1 (podríamos asignarle el valor 34 o -23), después la expresión de evaluación en este caso i<=5, es decirse ejecutará hasta que el valor de i sea menor o igual que 5 y por último el valor siguiente después de ejecutar el bloque que en este caso incrementa en 1 el valor de i (podríamos restarle 1 a i mediante –i o sumarle 2 mediante i+=2 aunque para VB.NET se utiliza Step.
Nota: La diferencia entre ++i y i++ es que la suma se realiza antes o después de asignarle un valor. Os muestro un ejemplo:

int i=3;
int j= ++i;
Console.WriteLine("Valor actual de j es {0}", j)
// Valor actual de j es 4;
i=3;
j= i++;
Console.WriteLine("Valor actual de j es {0}", j)
// Valor actual de j es 3;

Para VB.NET cerramos el bloque de código mediante la instrucción Next.
C#

class For_Prueba
    {
        static void Main()
        {
            Console.WriteLine("Salida");
            for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
    /* Salida:
    1
    2
    3
    4
    5
    */

Class For_Prueba
    Private Shared Sub Main()
        Console.WriteLine("Salida")
        For i As Integer = 1 To 5
            Console.WriteLine(i)
        Next
    End Sub
End Class
'
'    Salida:
'    1
'    2
'    3
'    4
'    5

Ejemplo de for obteniendo los números pares hasta 100
C#

for (int i = 1; i <= 100; i+=2)
{
       Console.WriteLine(i);
}

VB.NET

For i As Integer = 1 To 100 Step 2
       Console.WriteLine(i)
Next

Por último la instrucción foreach se utiliza para recorrer colecciones y ¿qué es una colección? Pues imaginemos que miramos la galería de fotos de nuestro móvil, seleccionamos una y vamos pasando una a una. Pues esto es lo que hace la instrucción foreach, pasar de una foto a otra por toda la colección.

¿Y qué hace? Pues el bloque de código contenido, se ejecutará para cada elemento de la colección. En el siguiente ejemplo, creamos una colección de números enteros y rotamos por cada uno de ellos. Como veis, esta instrucción tiene también varios elementos primero foreach, segundo y se ejecuta cada vez, crea un objeto del mismo tipo que los elementos de la colección y le asigna el valor de uno de estos y por último dice de donde debe extraer esos objetos. Pues para el siguiente caso se imprimirá por pantalla 0,1,1,2,3,5,8 y 13. Y a continuación expongo otra forma de recorrer una colección mediante una instrucción for diciendo que desde el valor con índice 0 hasta el valor menor que el número de elementos que tiene, imprima en pantalla el valor con el índice de la instrucción, curioso ¿no?

Para VB.NET foreach se convierte en For Each el valor del elemento declarado y la colección desde donde se extraerán los elementos acabando y cerrando el bloque de código con Next.
C#

int[] coleccion = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in coleccion)
{
         System.Console.WriteLine(element);
}
for (int i = 0; i < coleccion.Length; i++)
{
         System.Console.WriteLine(coleccion[i]);
}
/* En ambos casos, se imprime:
    0
    1
    1
    2
    3
    5
    8
    13
    */

Dim coleccion As Integer() = New Integer() {0, 1, 1, 2, 3, 5, 8, 13}
For Each element As Integer In coleccion
          System.Console.WriteLine(element)
Next
For i As Integer = 0 To coleccion.Length - 1
          System.Console.WriteLine(coleccion(i))
Next

Pues esto esto esto es todo amigos!!

Saludos “der Waki”

 

12.- Instrucciones de Selección

12.- Instrucciones de Selección
Las instrucciones son acciones que realiza el programa. Existen acciones comunes como la declaración de variables, la asignación de valores, la llamada a métodos, el recorrido en bucle de una colección y la creación de bifurcaciones a uno u otro bloque de código en función de una condición. El orden en que se ejecutan las instrucciones en un programa se denomina flujo de control o flujo de ejecución.Para C#, una instrucción puede estar compuesta por una única línea de código que finaliza en un punto y coma o por una serie de instrucciones de una línea incluidas en un bloque. Como ya hemos visto, un bloque de instrucciones se encierra entre llaves {} y pueden contener bloques anidados. A continuación enumero las categorías:

  • Instrucciones de selección (if, else, switch, case)
  • Instrucciones de iteración (do, for, foreach, in, while)
  • Instrucciones de salto (break, continue, default, goto, return, yield)
  • Instrucciones de control de excepciones (throw, try-catch, try-finally, try-catch-finally)
  • Checked y unchecked (checked, unchecked)
  • Instrucción fixed (fixed)
  • Instrucción lock

En VB.NET

En Visual Basic, una instrucción es una instrucción completa.  Puede contener palabras clave, operadores, variables, constantes y expresiones y cada instrucción como en C#, pertenece a cada una de las categorías siguientes:

Instrucciones de declaración, que dan nombre a una variable, constante o procedimiento y también pueden especificar un tipo de datos.

Instrucciones ejecutables, que inician acciones.  Estas instrucciones pueden llamar a un método o función, y pueden repetirse en bloques de código o crear una bifurcación en otro bloque de código. Las instrucciones ejecutables incluyen instrucciones de asignación, que asignan un valor o expresión a una variable o constante.

En este capítulo, vamos a ver las instrucciones de selección para C# y las instrucciones ejecutables para VB.NET.

¿Empezamos por C#? Venga, pues una instrucción de selección, hace que el programa vaya a un determinado punto dependiendo de que cierta condición sea verdadero o falso (true o false). Las palabras if, else, switch, case y default son las palabras clave en las instrucciones de selección. Como son palabras clave, no pueden usarse como variables o nombres de métodos ya que el compilador nos daría un error.

La instrucción if identifica que sentencia debe ejecutarse dependiendo de un valor booleano (verdadero o falso, true o false), vemos un ejemplo:

bool condition = true;
if (condition)
{
       Console.WriteLine("La variable tiene un valor true");
}
else
{
       Console.WriteLine("La variable tiene un valor false.");
}

Analicemos el código. Si la variable es true, (verdadera), visualizaremos en pantalla el texto de “La variable tiene un valor true”, pero si el valor lo cambiáramos a false, veríamos el segundo mensaje “La variable tiene un valor false”. El contenido donde se dirigirá el flujo del programa, se encuentra encerrado entre llaves {}, a continuación tenemos la palabra clave else y otras dos llaves con el contenido donde se redirigirá el programa cuando la condición es false.

En el siguiente ejemplo, declaramos una variable con valor entero y le asignamos el valor 8 y en la instrucción comparamos ese valor m para ver si es mayor que 10, ¿es mayor 8 que 10 (entre paréntesis)? Yo creo que no, pues entonces se aparecerá el mensaje “La variable tiene un valor false”.

int m = 8;
if (m > 10)
{
        Console.WriteLine("La variable tiene un valor true");
}
else
{
        Console.WriteLine("La variable tiene un valor false.");
}

También podríamos comparar si un texto es igual a otro mediante el operador ==

string texto = “mi_texto”;
if (texto == “mi_texto”)
{
	Console.WriteLine("La variable tiene un valor true");
}

También existe una combinación de if else y es que además podemos hacer una comparativa if y si falla esta, podemos hacer de nuevo otra comparación else if y si fallaran todas las instrucciones else if, redirigir el programa a la instrucción else.

int m = 8;
if (m > 10)
{
	Console.WriteLine("La variable tiene un valor true");
}
else if (m == 8)
{
	Console.WriteLine("La variable tiene un valor igual a 8");
} 
else
{
	Console.WriteLine("La variable tiene un valor false.");
}

La instrucción if tiene una forma simplificada como la que os represento

if (m > 10) {Console.WriteLine("La variable tiene un valor true");}
else {Console.WriteLine("La variable tiene un valor false.");}

(Esta versión es igual que las anteriores, pero con las llaves en la misma línea)
o

if (m > 10) Console.WriteLine("La variable tiene un valor true");
else Console.WriteLine("La variable tiene un valor false.");

Consejo: cuando no sepáis como funciona una instrucción, acudid a la referencia de msdn, ahí tenéis todo.

Otra instrucción de selección es switch en la que se redirige el programa a la lista de candidatos, en el siguiente caso, como es igual a 1, se redirigirá a la zona donde se imprimirá en pantalla “Caso 1”. Si por ejemplo el valor de la variable tuviera un valor de 17, como no existe ningún caso que valga 17, se ejecutaría la instrucción Default.

La palabra clave break, hace que una vez ejecutado el caso concreto, el programa se redirija fuera de la instrucción y no ejecute nada más dentro de esta.

int casoSwitch = 1;
switch (casoSwitch)
{
            case 1:
                Console.WriteLine("Caso 1");
                break;
            case 2:
                Console.WriteLine("Caso 2");
                break;
            default:
                Console.WriteLine("Caso Default");
                break;
}

En el lenguaje “der Waki”. ¿Existe algún caso que sea igual a 2? Pués claro!! Ir hasta el caso 2 e imprimir en pantalla “Caso 2”.

Otro caso, sería poder agrupar casos. En este concreto, hemos agrupado el caso 2,3 y 8, de modo que si la variable vale alguno de ellos, aparecerá el texto “Caso 2, 3 u 8”

        int casoSwitch = 3;
        switch (casoSwitch)
        {
            case 1:
                Console.WriteLine("Caso 1");
                break;
            case 2:
            case 3:
            case 8:
                Console.WriteLine("Caso 2, 3 u 8");
                break;
            default:
                Console.WriteLine("Caso Default");
                break;
        }

En Visual Basic .NET es muy parecido todo, pero existen algunas variaciones, primero que no existen llaves como en C#, estas se cambian por palabras clave, entonces para iniciar una instrucción if, esta comienza por lo mismo If, se añade la condición (sin paréntesis), palabra clave Then (entonces en inglés), el contenido del código que se ejecutará cuando sea verdadero, ElseIf o Else cuando queremos efectuar nuevas comparativas o la condición es falsa respectivamente y por fin le decimos al compilador que la instrucción finaliza con End If. ¿Bien? Prácticamente es igual!

Dim m As Integer = 8
If m > 10 Then
	Console.WriteLine("La variable tiene un valor true")
ElseIf m = 8 Then
	Console.WriteLine("La variable tiene un valor igual a 8")
Else
	Console.WriteLine("La variable tiene un valor false.")
End If

Para la instrucción switch iniciamos con Select Case y expresión Switch. Luego los casos, código del caso y salida de la instrucción Select Case.

Dim casoSwitch As Integer = 3
Select Case casoSwitch
	Case 1
		Console.WriteLine("Caso 1")
		Exit Select
	Case 2, 3, 8
		Console.WriteLine("Caso 2, 3 u 8")
		Exit Select
	Case Else
		Console.WriteLine("Caso Default")
		Exit Select
End Select

Igual pero con otras palabras!! Same, but with other words!!
Y si encima .NET, te permite escribir en varios lenguajes, pues que más da el que uses!! el que más fácil te resulte, ¿no?

Saludos “der Waki”

Nota: Si utilizáis Visual Studio, escribid dentro de un método la palabra if y pulsáis la tecla TAB dos veces. OHHH!! el fragmento de código, se escribe solo!!!

11.- Los campos, variables locales y tipos.

11.- Los campos, variables locales y tipos.
Vamos a tratar los campos, las variable locales y los tipos mediante una “minientrega”.Los campos, como ya dijimos, son variables declaradas a nivel de clase. Estos campos tienen como es lógico sus modificadores, es decir, pueden ser public, protected, prívate.

Aconsejo, no usar los campos como públicos sino privados o protegidos. ¿Por qué? Pues porque para ello ya usamos las propiedades y el campo lo que hace es respaldar el almacenamiento de estas.

Bueno hasta ahora no hemos descubierto nada, puesto que es repaso de lo aprendido, cuando declaramos un campo, lo definimos con un tipo, un número entero, doble precisión, fecha, cadena de texto, etc. Estos tipos pueden convertirse entre unos y otros, siempre que el compilador pueda hacerlo, en caso contrario provocaría un error. Puedo convertir una fecha a texto, pero lo que no puedo hacer es convertir la palabra “hola” en una fecha, el compilador se quejaría, ¿no?.

Una vez declarada una variable, ésta no se puede volver a declarar con un nuevo tipo y tampoco se le puede asignar un valor que no sea compatible con su tipo declarado. Por ejemplo, no puede declarar int y a continuación, asignarle un valor booleano de true. Sin embargo, los valores pueden convertirse en otros tipos, por ejemplo, cuando se asignan a variables nuevas o se pasan como argumentos de método.

Los tipos son:

Nombre de tipo
Descripción
System.Object
Clase base para todos los tipos. Puede almacenar cualquier cosa
System.String
Cadena de texto.
System.SByte
Byte con signo de 8 bits.
System.Byte
Byte sin signo de 8 bits.
System.Intl6
Valor de 16 bits con signo.
System.Ulntl6
Valor de 16 bits sin signo.
System.Int32
Valor de 32 bits con signo.
System.Ulnt32
Valor de 32 bits sin signo.
System.Int64
Valor de 64 bits con signo.
System.Ulnt64
Valor de 64 bits sin signo.
System.Char
Carácter unicode de 16 bits.
System.Single
Valor en coma flotante del IEEE de 32 bits.
System.Double
Valor en coma flotante del IEEE de 64 bits.
System.Boolean
Valor booleano (true!false).
System.Decimal
Tipo de
datos de 128-bit igual a 28 o 29 dígitos. Principalmente utilizado para aplicaciones
financieras, donde se requiere un alto grado de precisión.

Todos los tipos tienen un alias en el lenguaje de programación usado. ¿Y que es un alias?, pues un modo abreviado de acceder a ellos de una forma más rápida. Estos alias o nombres, no pueden ser utilizados para nombrar variables, están protegidos por el compilador, de modo que si intento declarar una variable con el nombre double, el compilador chillaría!

Y ¿por qué el tipo? Pues entre otras cosas, el tipo determina el almacenamiento interno en la memoria donde se guarda esta variable, el valor máximo y mínimo que puede representar, los miembros de clase que contiene (porque son clases), los tipos de operaciones que se pueden realizar con ellas, el tipo del que hereda y la ubicación en la memoria cuando se están en tiempo de ejecución. Con todo esto, el compilador se encarga de de comprobar que todos hacen las cosas como deben hacerlas.

Ejemplo.

C#

int a = 5;
int b = a + 2; //Esto funciona, suma 5 + 2 = 7
bool test = true;
int c = a + test; // Error. El operador '+' no puede sumar una variable de número con una variable tipo booleana.
string d = a.ToString() + test.ToString(); // Esto no da error ya que el resultado es ‘5True’, ahora las variable tipo número y booleana, las he convertido antes a texto y lo que ha hecho, ha sido concatenarlas

VB.NET

Dim a As Integer = 5
Dim b As Integer = a + 2
'Esto funciona, suma 5 + 2 = 7
Dim test As Boolean = True
Dim c As Integer = a + test
' Error. El operador '+' no puede sumar una variable de número con una variable tipo booleana.
Dim d As String = a.ToString() & test.ToString()' Esto no da error ya que el resultado es ‘5True’, ahora las variable tipo número y booleana, las he convertido antes a texto y lo que ha hecho, ha sido concatenarlas

No se si os habéis dado cuenta, pero cuando declaramos una variable con su tipo, en la misma declaración es posible asignarle un valor, de este modo no tenemos porque volver a escribirla y asignarle un valor.

Bueno, pues todas estas cosas, además las podemos realizar dentro de un método y en este caso, la variable se convierte en local del método y no es accesible nada más que dentro de este y tampoco, nos permitirá declarar una variable con el mismo nombre dentro del método.

¿Cuáles son los más utilizados? Pues depende para que los vayamos a usar; ahí viene cuando diseñamos la clase y debemos determinar qué valores van a usar los miembros de clase.

Por ejemplo, dentro de un método voy a incluir un contador dentro de un bucle y cada vez que se repita, se sumará la cantidad de 1; sé que “jamás” no sobrepasará el valor de 10000, vamos que no llegará al valor de 10000, pues creo que si declaro una variable de tipo entero (16 bit) será más que suficiente, (valor mínimo -2147483647 y máximo 2147483647 ala!!!) ahora si el valor que voy a almacenar es el resultado de una división y necesito un aproximación alta, utilizaré un doublé (valor mínimo 5,0×10-324 y valor máximo 1,7×10308. Vaya cifras astronómicas!, ¿no? pues depende para que, a veces se quedan cortas.

Pues lo prometido es deuda, entrega corta y a programar!! Practicad mucho!!

Saludos “der Waki”

10.- Las propiedades

10.- Las propiedades
Como ya dijimos, las propiedades es una mezcla entre método y campo, puesto que almacenan valores y además nos permiten hacer cálculos sobre ellos. Para el que accede a la propiedad, la ve como un campo.
Además, son miembros de clase que nos permiten leer, escribir o calcular un campo privado de la clase, es decir, nos permite leerlo, cambiarle su valor o calcularle uno nuevo.
Una propiedad genérica, tiene la siguiente estructura:

  • Contiene un descriptor Get. Se utiliza para leer la propiedad. Una propiedad sin este valor, se considera de solo escritura, puesto que no es posible leerla.
  • Contiene un descriptor Set. Se utiliza para asignar un valor a la propiedad. Si este descriptor no existiera, la propiedad sería solo de lectura y por tanto, sería como cuando vimos la constante, que era un campo de solo lectura.
  • Tiene un campo del mismo tipo que la propiedad y asociado a esta.

Las propiedades no son campos, por tanto no podemos pasar como argumento en un método una propiedad.

¿Qué usos le podemos dar a las variables? Pues podemos usarlas para validar datos antes de permitir un cambio, exponer los datos de forma transparente obtenidos desde otro origen o cuando se realiza una acción, por ejemplo si cambiamos su valor, se genera un evento avisándonos de que la propiedad ha cambiado.

¿Dónde se declaran las propiedades? Las propiedades se declaran a nivel de clase mediante el tipo, el nombre de la propiedad, el descriptor get y el descriptor set.

Ejemplo. En la siguiente propiedad, declaramos un campo month y le asignamos el valor 7. Acto seguido declaramos la propiedad pública Month y en la cual si nosotros solicitáramos su lectura, nos daría el valor del campo month, en este caso, nos daría el valor 7. Si dijéramos que la propiedad Month vale ahora 10 (Octubre), en el descriptor set, comprobaría que el valor que le pasamos es mayor que 0, que como mínimo vale 1 y menor que 13, que como máximo valga 12. Una vez efectuada la comprobación le asignaría el valor a la propiedad. ¿Qué ocurriría si le asignamos el valor 15? Pues como no cumple las condiciones de mayor de 0 y menor de 13 y no se asignaría ningún valor a la propiedad quedando en su estado anterior. El valor value, es el valor que asignamos a la propiedad. ¿bien?

C#

    private int month = 7;  // el campo month
    public int Month    // La propiedad Month
    {
        get
        {
            return month;
        }
        set
        {
            if ((value > 0) && (value < 13))             {                 month = value;            
        }         
    }     
} 

VB.NET

 
Private m_month As Integer = 7' el campo month
Public Property Month() As Integer' La propiedad Month
 		Get
 			Return m_month
 		End Get
 		Set(value As Integer)
 			If (value > 0) AndAlso (value < 13) Then
				m_month = value
			End If
		End Set
End Property

Otro ejemplo con nuestra clase preferida, la clase Vehiculo. Asignamos un propiedad a esta clase llamada Matricula y otra Potencia, pues vamos a crear una instancia de esta y vamos a leer y escribir sus propiedades.
C#

static void Main(string[] args)
{
     Console.WriteLine ("Comienza la App");
     Vehiculo miVehiculo = new Vehiculo();
     miVehiculo.Potencia = 120;
     miVehiculo.Matricula = "0000 XXX";
     Console.WriteLine(miVehiculo.Potencia);
     Console.WriteLine(miVehiculo.Matricula);
     Console.WriteLine("Pulse INTRO para finalizar..");
     Console.ReadLine();
} 

class Vehiculo
{
        public Vehiculo()
        {
            // código utilizado al instanciar la clase
        }
        private double _potencia;
        public double Potencia
        {
            get { return _potencia; }
            set { _potencia = value; }
        } 

        private string _matricula;
        public string Matricula
        {
            get { return _matricula; }
            set { _matricula = value; }
        }
}

VB.NET


Private Shared Sub Main(args As String())
       Console.WriteLine("Comienza la App")
       Dim miVehiculo As New Vehiculo()
       miVehiculo.Potencia = 120
       miVehiculo.Matricula = "0000 XXX"
       Console.WriteLine(miVehiculo.Potencia)
       Console.WriteLine(miVehiculo.Matricula)
       Console.WriteLine("Pulse INTRO para finalizar..")
       Console.ReadLine()
End Sub  

Private Class Vehiculo

       Public Sub New()
           ' código utilizado al instanciar la clase
       End Sub

       Private _potencia As Double
       Public Property Potencia() As Double
            Get
                 Return _potencia
            End Get
            Set(value As Double)
                _potencia = value
            End Set
       End Property
       Private _matricula As String
       Public Property Matricula() As String
            Get
                Return _matricula
            End Get
            Set(value As String)
                _matricula = value
            End Set
       End Property
End Class

En este ejemplo, desde el método de clase Main, creamos un objeto Vehículo llamado miVehiculo, le asignamos a la propiedad Potencia un valor de 120 , a la propiedad de Matrícula 0000 XXX y una vez asignadas, las imprimimos por pantalla.
¿Qué ocurre dentro de las propiedades? Cuando le asignamos un valor a la Propiedad Potencia, estamos accediendo al descriptor set dándole al valor del campo _potencia, el valor asignado de 120 pero en el siguiente paso, cuando lo imprimimos por pantalla accedemos al descriptor get y este lo que hace es ir a buscar el campo privado de clase _potencia y devuelve su valor que es 120. Así de fácil.

Otro ejemplo un poco más complejo.
C#

class Cuadrado
    {
        public double _lado;
        public Cuadrado(double s)  //constructor
        {
            _lado = s;
        }
        public double Area
        {
            get
            {
                return _lado * _lado;
            }
            set
            {
                _lado = System.Math.Sqrt(value);
            }
        }
        public double Volumen
        {
            get { return _lado * _lado * _lado; }
            set { _lado =System.Math.Pow( value, 1 / 3); }
        } 

static void Main(string[] args)
{
      Cuadrado MiCuadrado = new Cuadrado(4);
      Console.WriteLine(MiCuadrado.Area); // imprime por pantalla 16
      MiCuadrado.Area = 100; // ahora el lado vale 10, pero no lo vemos porque es un camp privado de clase
      Console.WriteLine(MiCuadrado.Volumen); // imprime por pantalla 1000
 }

VB.NET

Class Cuadrado
        Public _lado As Double
        Public Sub New(s As Double)
           'constructor
            _lado = s
        End Sub
        Public Property Area() As Double
            Get
                Return _lado * _lado
            End Get
            Set(value As Double)
                _lado = System.Math.Sqrt(value)
            End Set
        End Property
        Public Property Volumen() As Double
           Get
                Return _lado * _lado * _lado
           End Get
           Set(value As Double)
               _lado = System.Math.Pow(value, 1 \ 3)
           End Set
        End Property
End Class

Private Shared Sub Main(args As String())
            Dim MiCuadrado As New Cuadrado(4)
            Console.WriteLine(MiCuadrado.Area)
            ' imprime por pantalla 16
            MiCuadrado.Area = 100
            ' ahora el lado vale 10, pero no lo vemos porque es un camp privado de clase
End Sub

Creamos una clase Cuadrado a la cual le agregamos una propiedad llamada Area con un campo llamado _lado. En el constructor de la clase, (lo primero que hace una clase cuando se instancia), le agregamos un parámetro s, de modo que cuando instanciemos la clase Cuadrado, nos pedirá que le pasemos un argumento, en este caso el valor del lado el cual automáticamente es asignado al campo _lado. Hasta aquí todo bien.

Si le pedimos al objeto cuadrado el valor de su Area, el descriptor get, obtendrá el valor de _lado y lo multiplicará por si mismo, obteniendo el Area que solicitamos.

Si ahora le dijéramos a este objeto que el valor de su Area es 100, el descriptor set calcularía la raíz cuadrada del área para asignar al campo _lado este valor, en este caso 10, por tanto al solicitarle que imprima por pantalla la propiedad Volumen, este ha calculado el nuevo valor del lado y el nuevo valor del volumen. Este es uno de los poderes secretos de las propiedades. Fantástico ¿no?

Ahora que sabemos que son las propiedades, más adelante crearemos algunas más complejas que nos avisen cuando cambie su valor generando eventos.

Saludos “der Waki”

9.- Los métodos

9.- Los métodos
Como dijimos, los métodos son las acciones realizadas por el objeto. En la cuarta entrega, escribíamos con el “lenguaje der Waki” la clase Vehículo con los métodos Avanzar, Arrancar o Parar. En el método Avanzar le añadíamos la velocidad hasta la que queríamos que nuestro vehículo llegara.
El valor velocidad es el parámetro del método, es el que aparece en el método, mientras que el argumento es el valor pasado una vez creado el objeto. Ejemplo.
C#


/* ************************************************
* © WAKI 2014
* PROYECTO:        Aprender a Programar.
* Archivo:         Program.cs
* Descripción:     Clase Main y Vehículo
* Historial:
* Comentarios:
*
****************************************************/
using System;
namespace MyNameSpace
{
    class MyApp
    {
        static void Main(string[] args)
        {
            Console.WriteLine ("Comienza la App ==>");
            Vehiculo miVehiculo = new Vehiculo();

            miVehiculo.Avanzar(50); // esto hace avanzar el vehículo hasta los 50km/h. 50 es el ARGUMENTO
            Console.WriteLine ("Pulse una tecla para frenar el vehículo...");
            Console.ReadLine();
            miVehiculo.Avanzar(0); // esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine("Pulse INTRO para finalizar..");
            Console.ReadLine();
       }
    }
    class Vehiculo
    {
        public Vehiculo()
        {
            // código utilizado al instanciar la clase
        }
        public void Avanzar(int kmHora)
        {
            // kmHora es el parámetro tipo número entero del método Avanzar
            Console.WriteLine("La velocidad del vehículo es de " + kmHora.ToString() + " km/h");
        }
    }
}

VB.NET

' ************************************************
'* © WAKI 2014
'* PROYECTO:        Aprender a Programar.
'* Archivo:         Program.cs
'* Descripción:     Clase Main y Vehículo
'* Historial:
'* Comentarios:
'*
'***************************************************
Namespace MyNameSpace
    Class MyApp
        Private Shared Sub Main(args As String())
            Console.WriteLine("Comienza la App ==>")
            Dim miVehiculo As New Vehiculo()

            miVehiculo.Avanzar(50)
            ' esto hace avanzar el vehículo hasta los 50km/h. 50 es el ARGUMENTO
            Console.WriteLine("Pulse una tecla para frenar el vehículo...")
            Console.ReadLine()

            miVehiculo.Avanzar(0)
            ' esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine("Pulse INTRO para finalizar..")
            Console.ReadLine()
        End Sub
    End Class

    Class Vehiculo
        ' código utilizado al instanciar la clase
        Public Sub New()
        End Sub

        Public Sub Avanzar(kmHora As Integer)
            ' kmHora es el parámetro tipo número entero del método Avanzar
            Console.WriteLine("La velocidad del vehículo es de " & kmHora.ToString() & " km/h")
        End Sub
    End Class
End Namespace

Analizando código…

  1. Escribimos en la consola “Comienza App ==>”
  2. Creamos el objeto miVehiculo
  3. Llamamos al método Avanzar de miVehículo pasando el argumento 50
  4. Se visualiza en la consola “La velocidad del vehículo es de 50 Km/h”
  5. Escribimos en la consola “Pulse una tecla para frenar el vehículo…”
  6. Al pulsar INTRO, llamamos de nuevo al método Avanzar de miVehículo pasando el argumento 0
  7. Se visualiza en la consola “La velocidad del vehículo es de 0 Km/h”
  8. Al pulsar INTRO finalizamos.

Nota: Solo hay detalle nuevo que se nos pasa por alto y es
que en C# ¿se suman las palabras?. El texto se concatena en C# mediante el
signo + mientras que en VB.NET es mediante el signo &. Estos son operadores
y los hay a miles (no tantos Waki!).
Un método puede contener múltiples parámetros y de cualquier índole. Podría crear una clase a la
que pasará como un argumento un objeto tipo Vehículo, cualquier objeto admite,
ahora si, si la clase o el método tiene como parámetros un objetos tipo
Vehículo, solo y exclusivamente podemos pasarle este tipo de objeto y no un
número del tipo int, Integer o entero, un string o cadena, o booleano, etc
Más cosas con los métodos, podemos crear métodos con el mismo nombre pero con distinto tipo de parámetros.  Esto se llama sobrecarga y permite utilizar un
mismo método de diferente forma como en la vida misma o ¿nosotros caminamos siempre del mismo modo?,  a pesar de que
el método caminar es el mismo, podemos hacerlo calzados o descalzados (con lo que variaría la velocidad), el tipo de calzado, hacia atrás, hacia adelante,
etc. Expongo un ejemplo.
C#

public void Avanzar(int kmHora)
{
      // kmHora es el parámetro tipo número entero del método Avanzar
      Console.WriteLine("La velocidad del vehículo es de " + KmHora.ToString() + " km/h");
}

public void Avanzar()
{
     // avanza hasta los 50 Km/h como valor predeterminado
     Console.WriteLine("La velocidad del vehículo es de 50 km/h");
}

public void Avanzar(int kmHora, bool limitarA120)
{
	// kmHora es el parámetro tipo número entero del método Avanzar
	// limitarA120 no permite que pase de 120 km/h
	if (limitarA120 && kmHora > 120)
	{
		kmHora = 120;
	}
       Console.WriteLine("La velocidad del vehículo es de " + kmHora.ToString() + " km/h");
}

VB.NET

Public Sub Avanzar(kmHora As Integer)
    ' kmHora es el parámetro tipo número entero del método Avanzar
    Console.WriteLine("La velocidad del vehículo es de " & kmHora.ToString() & " km/h")
End Sub

Public Sub Avanzar()
    ' avanza hasta los 50 Km/h como valor predeterminado
    Console.WriteLine("La velocidad del vehículo es de 50 km/h")
End Sub

Public Sub Avanzar(kmHora As Integer, limitarA120 As Boolean)
    ' kmHora es el parámetro tipo número entero del método Avanzar
    ' limitarA120 no permite que pase de 120 km/h
    If limitarA120 AndAlso kmHora > 120 Then
        kmHora = 120
    End If
    Console.WriteLine("La velocidad del vehículo es de " & kmHora.ToString() & " km/h")
End Sub

Tres métodos Avanzar pero con distintos parámetros. El primero permite llevar al vehículo a una velocidad concreta, el segundo lleva al vehículo a una velocidad predeterminada y el tercero lleva un parámetros que nos va a permitir limitar la velocidad a 120 Km/h. Si el segundo argumento pasado (parámetro limitarA120), tiene un valor false, (falso), se comporta como el método primero, pero si el argumento pasado tiene un valor true, (verdadero), el método limitará la velocidad a 120. ¿Cómo? Mediante el fragmento if o If…

La instrucción if para C# o If…Then para VB.NET tiene muchas variantes, pero esta es la más sencilla. Lo primero que hace es efectuar una comparación booleana, quiere decir que se obtendrá un Sí o un No, un Verdadero o un Falso, un true o un false. Dentro de esta condición hacemos otra comparación mediante el operador && o AndAlso que es el operador equivalente a decir Y; en el método preguntamos, ¿es verdadero el argumento pasado limitarA120? Y además ¿es verdadero que el argumento pasado de velocidad es mayor que 120? Pues si esto es verdadero, se limitará la velocidad a 120 Km/h, pero si alguno de las condiciones de la instrucción if no se cumple, el argumento limitar es falso o la velocidad es inferior a 120, pues no se limitará. ¿OK? Pues tan útil como ya he dicho se llama sobrecarga de métodos.

Por último, los métodos también pueden devolver valores. Si le pedimos a una calculadora que sume dos número, primero nos solicitará los dos números y luego el método suma, devolverá un resultado con las dos cantidades sumadas, bien, pues a un método por ejemplo le pasamos dos argumentos y este, devuelve la suma de ambos. En VB.NET los métodos que devuelven valores se llaman funciones. Ejemplos es lo que nos hace falta!. Vamos a convertir los tres métodos del ejemplo anterior pero devolviendo el texto que escribimos en la consola, evitando incluir Console.WriteLine en cada método.

C#

/* ************************************************
* © WAKI 2014
* PROYECTO:        Aprender a Programar.
* Archivo:         Program.cs
* Descripción:     Clase Main y Vehículo
* Historial:
* Comentarios:
*
****************************************************/

using System;
namespace MyNameSpace
{
    class MyApp
    {
        static void Main(string[] args)
        {
            Console.WriteLine ("Comienza la App");
            Vehiculo miVehiculo = new Vehiculo();
            string textoDeSalida = miVehiculo.Avanzar(90); // esto hace avanzar el vehículo hasta los 90km/h. 90 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine ("Pulse una tecla para frenar el vehículo...");

            Console.ReadLine();
            textoDeSalida = miVehiculo.Avanzar(0); // esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse una tecla para activar velocidad predeterminada...");
            Console.ReadLine();

            textoDeSalida = miVehiculo.Avanzar(); // esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse una tecla para limitar velocidad...");
            Console.ReadLine();

            textoDeSalida = miVehiculo.Avanzar(150,true); // velocidad a 150 km/h y limitador activado
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse INTRO para finalizar..");
            Console.ReadLine();
        }
    }

    class Vehiculo
    {
        public Vehiculo()
        {
            // código utilizado al instanciar la clase
        }

        public string Avanzar(int kmHora)
        {
            // kmHora es el parámetro tipo número entero del método Avanzar
            return "La velocidad del vehículo es de " + kmHora.ToString() + " km/h";
        } 

        public string Avanzar()
        {
            // avanza hasta los 50 Km/h como valor predeterminado
            return "La velocidad del vehículo es de 50 km/h";
        } 

        public string Avanzar(int kmHora, bool limitarA120)
        {
            // kmHora es el parámetro tipo número entero del método Avanzar
            // limitarA120 no permite que pase de 120 km/h
            string textoDeSalida = "La velocidad del vehículo es de "; 

            if (limitarA120 && kmHora > 120)
            {
                textoDeSalida = "La velocidad del vehículo era de " + kmHora + " Km/h, pero ahora es de ";
                kmHora = 120;
            }
            return  textoDeSalida + kmHora.ToString() + " km/h";
        }
    }
}

VB.NET

/* ************************************************
* © WAKI 2014
* PROYECTO:        Aprender a Programar.
* Archivo:         Program.cs
* Descripción:     Clase Main y Vehículo
* Historial:
* Comentarios:
*
****************************************************/
using System;
namespace MyNameSpace
{
    class MyApp
    {
        static void Main(string[] args)
        {
            Console.WriteLine ("Comienza la App");
            Vehiculo miVehiculo = new Vehiculo();
            string textoDeSalida = miVehiculo.Avanzar(90); // esto hace avanzar el vehículo hasta los 90km/h. 90 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine ("Pulse una tecla para frenar el vehículo...");
            Console.ReadLine();

            textoDeSalida = miVehiculo.Avanzar(0); // esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse una tecla para activar velocidad predeterminada...");
            Console.ReadLine();

            textoDeSalida = miVehiculo.Avanzar(); // esto hace parar. 0 es el ARGUMENTO
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse una tecla para limitar velocidad...");
            Console.ReadLine();

            textoDeSalida = miVehiculo.Avanzar(150,true); // velocidad a 150 km/h y limitador activado
            Console.WriteLine(textoDeSalida);   // Aquí se imprime el texto devuelto por los métodos
            Console.WriteLine("Pulse INTRO para finalizar..");
            Console.ReadLine();
        }
    }

    class Vehiculo
    {
        public Vehiculo()
        {
            // código utilizado al instanciar la clase
        }

        public string Avanzar(int kmHora)
        {
            // kmHora es el parámetro tipo número entero del método Avanzar
            return "La velocidad del vehículo es de " + kmHora.ToString() + " km/h";
        }

        public string Avanzar()
        {
            // avanza hasta los 50 Km/h como valor predeterminado
            return "La velocidad del vehículo es de 50 km/h";
        } 

        public string Avanzar(int kmHora, bool limitarA120)
        {
            // kmHora es el parámetro tipo número entero del método Avanzar
            // limitarA120 no permite que pase de 120 km/h
            string textoDeSalida = "La velocidad del vehículo es de ";
            if (limitarA120 && kmHora > 120)
            {
                textoDeSalida = "La velocidad del vehículo era de " + kmHora + " Km/h, pero ahora es de ";
                kmHora = 120;
            }
            return  textoDeSalida + kmHora.ToString() + " km/h";
        }
    }
}

Analizando código… en el método Main, ocurre lo siguiente:

  1. Escribimos en la consola “Comienza App ==>”
  2. Creamos el objeto miVehiculo
  3. Llamamos al método Avanzar(90) de miVehículo pasando el argumento 90
  4. Se visualiza en la consola “La velocidad del vehículo es de 90 Km/h”
  5. Escribimos en la consola “Pulse una tecla para frenar el vehículo…”
  6. Al pulsar INTRO, llamamos de nuevo al método Avanzar(0) de miVehículo pasando el argumento 0
  7. Se visualiza en la consola “La velocidad del vehículo es de 0 Km/h”
  8. Escribimos en la consola “Pulse una tecla para activar velocidad predeterminada…”
  9. Al pulsar INTRO, llamamos de nuevo al método Avanzar() sin argumentos de miVehiculo.
  10. Se visualiza en la consola “La velocidad del vehículo es de 50 Km/h”
  11. Escribimos en la consola “Pulse una tecla para limitar velocidad…”
  12. Al pulsar INTRO, llamamos de nuevo al método Avanzar(150) de miVehículo pasando el argumento 150
  13. Se visualiza en la consola “La velocidad del vehículo era de 150 Km/h, pero ahora es de 120 Km/h.”
  14. Al pulsar INTRO finalizamos.

En el último método Avanzar creamos una variable textoDeSalida, a la cual le damos un valor u otro dependiendo si se limita la velocidad o no y para devolver los valores al lugar desde los hemos llamado es mediante la instrucción return que retorna o devuelve el valor calculado.

Para la sobrecarga de métodos, lo único que no podemos hacer es crear dos métodos con el mismo número de parámetros y del mismo tipo, lo que provocaría una ambigüedad y el compilador no sabría cual ejecutar.

Como ya sabemos compilar, practica y crea, que no duele!

Saludos “der Waki”

7.- Un modo de tener el código ordenado

7.- Un modo de tener el código ordenado
Como ya dije en el Post 5, el coste llevado a cabo para el mantenimiento del software es muy costoso, por lo que sería muy conveniente escribir un código muy comentado, claro y estructurado, esto nos daría limpieza y efectividad pudiendo detectar y minimizar los ERRORES (porque haberlos, “haylos”)
Para comentar el código, escribimos en C#
// Aquí van los comentarios
o en VB.NET
’Aquí van los comentarios.
Este texto en Visual Studio se torna verde cuando se trata de un comentario.
Si en vez de dos barras, escribimos tres, podemos escribir comentarios continuamente al pulsar ENTER y cambiar de línea, escribiéndose automáticamente otras tres barras (C#) o comillas simples(”’).
Si estamos programando en Visual Studio y escribimos estas tres barras o comillas simples encima de un método, variable, propiedad, etc., es decir sobre un miembro de clase, se inserta automáticamente una etiqueta llamada <summary> con otra etiqueta de cierre </summary> y el contenido que escribamos entre estas dos etiquetas se visualizará automáticamente con IntelliSense
que es una herramienta de ayuda de Visual Studio con la cual según vamos escribiendo, se van visualizando los miembros de clase disponibles en esta;
además visualiza la información escrita entre las dos etiquetas <summary>Esto describe el miembro de clase </summary>.
Una vez comentado el código, existe otra forma de tener el código ordenado mediante bloques y esto se hace escribiendo
C#

#region MyRegion

// aquí podemos poner todos los

// miembros de clase que queramos
#endregion

VB.NET

#Region "MyRegion"
        ' aquí podemos poner todos los
        ' miembros de clase que queramos
#End Region

Esto no se compila y simplemente nos permite mantener los miembros de clase ordenaditos y enclaustrados entre regiones o bloques de código, por ejemplo, podemos crear una región llamada propiedades y variables donde incluyamos solo exclusivamente estos miembros u otra donde incluya los métodos asociados a controles y dentro de esta más bloques de código separándolos por tipo de control, de modo que cuando quiera visualizar un método asociado a un evento click de un botón, me iré a la región Controles y dentro de esta a otra región llamada Botones y en su interior estará el método que busco evitando dar muchas vueltas con la rueda del ratón o efectuando búsquedas de texto.Debemos pensar que el código será revisado por otra persona o por nosotros mismos miles de años después, por tanto, ordena!!! (¿miles? jajajaja dejémoslo en cientos).
Además, imaginemos una clase con 1000 líneas, al incluir el código entre regiones, es posible contraer o expandir las regiones, evitando mantener las mil líneas desplegadas con el consiguiente lio.
Otra forma de de mantener claro el código es escribir con mucha sencillez los métodos, espaciados y con pocas líneas (A ser posible).
Otro aspecto muy importante es la nomenclatura de los nombres de las clases y miembros de clase, ¿por qué es importante? Pues si recuerdan cuando en el lenguaje “der waki” asignábamos los nombres a las características y métodos de la clase vehículo, los nombrábamos con Velocidad, Potencia, Matrícula, Número de Bastidor, Arrancar, Parar, Avanzar, etc., pues eso, cuando quiero asignarle la matrícula a la propiedad Matrícula debo hacerlo con sentido común; si le hubiéramos puesto como nombre Abrigo, diría ¿para qué le he puesto el nombre Abrigo a la propiedad Matrícula?
Menuda tontería no!! Pues por ahí van los tiros.

Existen múltiples notaciones para nombrar los miembros de clase, pero nos centramos en dos, notación Pascal y Camello ( que nombres!!). La notación Pascal utiliza la primera letra de cada palabra con mayúscula, de modo que si nombramos la propiedad NumeroBastidor, iniciamos cada palabra con mayúsculas sin espacios y si usamos la notación camello es igual que la Pascal pero iniciando con minúsculas y dándole ese aspecto de jorobas de camello subiendo y bajando.
Microsoft utiliza este método para crear sus aplicaciones y dependiendo del miembro
de clase que sea, adaptaremos el nombre de un modo u otro y que a continuación detallo:

  • Espacios de nombres. Para los espacios de nombres se usa el nombre de la compañía o el nombre del producto con la primera letra en mayúscula y resto en minúsculas, por ejemplo Microsoft tiene un espacio de nombres Microsoft de alto nivel y según van creando productos, le agregan un nuevo espacio de nombres,  Microsoft.Win32,  System.Windows.Forms, etc.
  • Para las clases, utilizamos sustantivos con notación Pascal. Otra manía que tengo y que aprendí de dos buenos programadores, es encabezar las clases con comentarios, nombre del archivo de la clase, que hace la clase, quien la ha creado y cuando, si le introduzco modificaciones, que modificaciones se han realizado y cuando, en definitiva, una serie de datos que me informen de la clase.
  • Para los métodos también Notación Pascal, pero como los métodos hacen cosas, actúan, llevan a cabo una labor, interesa que describan los que hacen mediante verbos acompañados de objeto sobre el que recae la acción. Por ejemplo ImprimirFactura, CalcularSalario, AbrirBaseDeDatos, ObtenerUsuario, etc. Yo personalmente, uso en castellano los métodos privados y los métodos públicos los pongo en inglés para globalizar la clase, si estos métodos los hiciera públicos, les daría PrintInvoice, CalculatePay,OpenDataBase, GetUser, etc. Debo hacer hincapié en que existen métodos que además de hacer algo obtienen algo, como el último ejemplo ObtenerUsuario que se encargaría de buscar en algún sitio el usuario que está activo en el momento, bueno pues existen métodos que comprueban algo por ejemplo EstaLaPuertaAbierta
    y si lo está, devolvería un valor verdadero y si no lo está devolvería un valor
    falso, este tipo se llaman boolean de Boole el matemático que estudio el algebra de su mismo nombre sobre el sistema binario, pues este tipo de métodos deben comenzar con la tercera persona del verbo ser o estar, en inglés Is, por ejemplo IsOpenDoor, de modo que si utilizamos este método con alguna condición, sería mucho más claro de entender, en el lenguaje “der Waki”

Si está abierta la puerta, ciérrala

En C#

if (IsOpenDoor())
{
     // cerrar puerta
}

En VB.NET

If IsOpenDoor() Then
     ' cerrar puerta
End If
  • Las propiedades. Estilo Pascal (primera en mayúscula de cada palabra)
  • Variables. Sobre las variables o campos, hay tema para todos los gustos. Vamos a ver, si una clase se llama Autor y creamos un campo que identifique al autor, no vamos a ponerle el mismo nombre de la clase, le ponemos por ejemplo NombreAutor con notación Pascal y cuando accedamos a esta variable los haremos mediante Autor.NombreAutor. Para las variables privadas o de menor entidad, yo utilizo la notación Camello (primera en minúsculas) y en algunos casos (para gustos los colores) le incluyo a la notación camello un guión bajo al inicio, así de un primer vistazo introduciendo un guión, echo un vistazo sobre estas.

De todos modos, los IDE (Entornos de Desarrollo Integrado) como Visual Studio, Eclipse, etc.., cambian de color (como los comentarios que los ponía en verde) cada elemento dependiendo del tipo que sea.

En resumen, para todo programador es importantísimo el orden, tengo la experiencia de crear aplicaciones con pocas líneas de código y que al volver a modificar algún detalle, volverse en un trabajo tedioso, por tanto el tiempo invertido inicialmente es fundamental para futuras modificaciones o ampliaciones.

Saludos “der Waki”

5.- Primer contacto con el código

5.- Primer contacto con el código

Por fin vamos a comenzar a escribir código!!! (pero poco, que luego nos liamos)

Hay una gran variedad de lenguajes, pero en principio nos vamos a centrar en .NET y los lenguajes que usamos para .NET.¿Qué es .NET? Es una plataforma a la que las aplicaciones acceden a coger lo que les hace falta, de ese modo cada vez que desarrollamos una aplicación no tiene porque llevar consigo ciertas herramientas. Con esto conseguimos que todo el mundo use las mismas utilidades y del mismo modo.

De los componentes que tiene .NET Framework nos enfocamos en dos, el CLR (Common Language Runtime) y la biblioteca de clases.

El primero es un entorno de ejecución que asegura que el código escrito cumple una serie de reglas, (vamos que es bueno!) y por otra parte compila desde un lenguaje intermedio (MSIL) al código nativo. El CLR nos permite poder crear una clase en Visual Basic, crear dos heredadas de esta en C# y C++. Que cosas!!

La biblioteca de clases contiene todas las clases base, (valga la redundancia), para todos los lenguajes de programación. En definitiva, da igual el lenguaje que utilicemos, todos valen!.

Antes de continuar, vamos a repasar alguna palabra nueva.

¿Que es compilar? es convertir un lenguaje a otro, normalmente a código máquina. ¿Y que es código máquina? es el lenguaje que solamente entiende un microprocesador, el chip principal de nuestro PC.

Por tanto, generamos clases C#, VB, .. el compilador lo convierte a MSIL y posteriormente el CLR se encargará de compilar a código máquina con otro compilador (Just In Time JIT ) lo que vayamos necesitando. (Es bastante más complicado, pero dejémoslo ahí, más o menos).

Y yo ¿qué necesito para crear un programa? pues un editor de texto, por ejemplo el bloc de notas (Notepad.exe) o yo, personalmente utilizo notepad++,  (lo utilizo mucho para HTML) tabula, cambia el color de variables, métodos, tiene múltiples lenguajes, etc, y por último un compilador.

¿Dónde consigo el compilador? Al instalar .NET Framework, se instalan también los compiladores, por lo que podemos compilar desde la línea de comandos (csc para C# y vbc para VB. Ya lo haremos! poco a poco.

Pero entonces, ¿por qué tenemos que instalar Visual Studio? Visual Studio es un IDE (Entorno de Desarrollo Integrado), el cual tiene un conjunto de herramientas para diferentes lenguajes como  C++, C#, Visual Basic .NET, F#, Java, Python, Ruby, PHP y para entornos de desarrollo ASP.NET que te AYUDAN MUCHÍÍÍÍÍÍSIMO a crear aplicaciones, por tanto os insto a usarlo. Microsoft, tiene una versión de Visual Studio Express gratuita, te registras y a programar!

Como dije vamos a aprender dos lenguajes muy comunes C# (la almohadilla se lee Sharp, por tanto C Sharp) o Visual Basic .NET.

Cuando creamos la clase vehículo o camión, yo ponía en el lenguaje “der waki”, comienza declaración de clase, pues eso, cuando se genera una clase, hay que poner lo siguiente:

En C#


using Espacio_de_nombres1;
using Espacio_de_nombres1;

namespace espacio_de_nombres
{
public class Class1
{
// aquí va el código    }
}

en VB:NET


Imports espacio_de_nombres1
Imports espacio_de_nombres2

Namespace espacio_de_nombres
Class [MyClass]
' aquí va el código
End Class
End Namespace

En primer lugar ¿Qué es la palabra using o Imports? La biblioteca de clases de .NET Framework tiene un entramado jerárquico de clases enorme y algunos nombres bastante largos. Si tenemos que usar alguna de las clases de alguna biblioteca, tendríamos que escribir continuamente los espacios de nombre a la que pertenecen las clases ( y algunos son largos, largos), pues de este modo, una vez incluidos mediante using o Imports, no es necesario escribir continuamente y si
el compilador no entiende algo que he escrito, se encarga de buscarlo en la
lista de using.

¿Qué es el espacio de nombres? Los espacios de nombres se utilizan en gran medida en la programación de dos maneras. En primer lugar, .NET Framework utiliza los espacios de nombres para organizar sus múltiples clases. En segundo lugar, declarar espacios de nombres propios puede ayudar a controlar el ámbito de clase y nombres de método en proyectos de programación grandes. Concluyendo, son contenedores de clases que nos ayudan a mantenerlas ordenadas y localizadas. Si creo 5 clases distintas pero están todas en el mismo namespace, podré acceder a cualquiera de ellas a través de este por ejemplo escribiendo namespace1.clase3.

Para declarar la clase, utilizamos las llaves en C#, mientras que en VB
Iniciamos con Class y finalizamos con End Class. Dentro de la clase, escribiremos el código.

Donde ponía Nota, en C# es // y después los comentarios y en
VB.NET la comilla simple ‘.

Ojo!!, en C#, las líneas deben acabar con punto y coma “;”.

Como consejo, diría que a la hora de escribir código, hay que respetar
escrupulosamente los nombres mediante una notación específica, respetar
tabulaciones, comentar, en definitiva limpieza porque si un programa es grande,
la cosa se puede complicar muy mucho, además, si trabajáramos en un equipo de
trabajo, lo que estoy diciendo se convertiría en condición indispensable. El mantenimiento de las aplicaciones es muy costoso y si no tenemos el código limpio, mal vamos!, dedicaremos un post solo a la notación.

Nos quedamos aquí por hoy, pero recuerden, aún hay mas!!!

Saludos “der waki”

 

 

4.- Y ahora, creo un objeto heredado

4.- Y ahora, creo un objeto heredado

En esta entrega vamos a crear un objeto utilizando la herencia y el polimorfismo, creando una nueva clase que va a heredar las características y las funciones de su “padre” además de añadirle las suyas propias.

Volviendo de nuevo al código “der waki”, vamos a utilizar la clase vehículo de la anterior entrega para crear una clase nueva llamada camión.

Un camión como dijimos, sigue siendo un vehículo pero agregándole nuevas características; una era la capacidad de la caja y otra avanzar con reductora (para los que no sepan lo que es reductora es una caja de cambios especial que mediante ruedas dentadas como no podía ser de otro modo, obtiene potencia en perjuicio de velocidad, mas fuerza!!). Comenzamos.Declaro Camión. Heredo de Vehículo. Nota: Herencia!!!

(comienza declaración de clase)

Nota:  Características

propiedad capacidad. Esto es número.

Nota: ahora declaro los métodos

Nota: Este método es igual que el de vehículo, ahora tenemos dos método llamados avanzar, uno el que hemos heredado de vehículo y el otro que estamos creando ahora. Solo hay que especificar cual utilizar.

método Avanzar (¿Hasta que velocidad?)

(comienza método)

Nota: Polimorfismo!!!

Requisitos. El vehículo debe estar arrancado, el vehículo no debe tener el freno de mano echado….

Acciones.  Activar caja de cambios reductora. Llevar el coche a la velocidad del método. Envío más o menos combustible a los inyectores dependiendo de como esté pisado el acelerador y como es automático, el embrague se ha accionado y la caja de cambios engrana con otros métodos internos y … (encapsulación), más acciones que no vemos!!

(finaliza método)

(finaliza declaración de clase)

Ahora ya que tenemos la plantilla, vamos a crear el objeto Camión.

Crear un nuevo Vehículo como Camión que voy a llamar camión “der waki”

Nota: He hecho esto para instanciar un vehículo pero como camión, ¿para que? para que cuando inicie el método avanzar lo haga con la reductora.

la matrícula del camión der waki es 0001 AAA. Nota: Esta propiedad es heredada

el número de bastidor de camión der waki es YYYYYY. Nota: Esta propiedad es heredada

la potencia de camión der waki es 250 CV. Nota: Esta propiedad es heredada

la velocidad de camión der waki es 0 km/h. Nota: Esta propiedad es heredada

la capacidad de camión der waki es 36 metros cúbicos. Nota: Esta propiedad es solo del camión!

Ordeno al camión der waki Arrancar Motor

Ordeno al camión der waki Avanzar. Nota: Avanzará con reductora porque hemos instanciado un vehículo pero como camión, por tanto utilizará el método avanzar de camión, es decir con reductora.

Ordeno al camión der waki  Parar Motor

Bueno, pues en esta clase, hemos intentado adaptar los principios fundamentales de la programación, herencia, encapsulación y polimorfismo creando un nuevo objeto heredado y con funciones sobrescritas.

Saludos “der Waki”

PD. Tengo que hacer un inciso sobre las propiedades de una clase; cuando he declarado una propiedad, le he dicho esto es texto, esto es un número, esto es una fecha, etc… bueno, esto es un aspecto que hay que tener en cuenta, cuando declaramos las propiedades o variables de una clase, tenemos que decirle que son y que van a albergar en su interior de modo que estén preparadas, bueno realmente lo que estamos es instanciar nuevas clases y estas, tiene métodos propios del tipo que sea. Por ejemplo, si incluimos una nueva propiedad a la clase vehículo como fecha de fabricación, no sería válido ponerle el 42 de Febrero de 2014,  ya que la clase de fechas no permitiría tal aberración.