jueves, 28 de febrero de 2019

Constructores y destructores



CONSTRUCTORES Y DESTRUCTORES


¿Que es un constructor en c#?

Constructores en C#

Cada vez que se crea una clase o estructura, se llama a su constructor. Una clase o estructura puede tener varios constructores que toman argumentos diferentes. Los constructores permiten al programador establecer valores predeterminados, limitar la creación de instancias y escribir código flexible y fácil de leer.

En C# podemos definir un método que se ejecute inicialmente y en forma automática. Este método se lo llama constructor.

El constructor tiene las siguientes características:
  • Tiene el mismo nombre de la clase.
  • Es el primer método que se ejecuta.
  • Se ejecuta en forma automática.
  • No puede retornar datos.
  • Se ejecuta una única vez.
  • Un constructor tiene por objetivo inicializar atributos.

Sintaxis de un Constructor en C#

Modificador NombredelaClase (Parámetros)
{
   Instrucciones
}

Veamos un Ejemplo de un constructor en C#

using System;

namespace constructores
{
    class EjConstructor
    {
        int a;
        int b;
        //declaramos el constructor
        public EjConstructor(int x, int y)
        {
            a = x;
            b = y;
        }
        public int Suma()
        {
            return a + b;
        }

        public int resta()
        {
            return a - b;
        }

        class Principal
        {
            static void Main(string[] args)
            {
                //creamos objeto de la clase y le pasamos los parametros al constructor
                EjConstructor obj = new EjConstructor(10, 20);
                Console.WriteLine("La suma es: "+obj.Suma());
                Console.WriteLine("La resta es: "+obj.resta());
                Console.ReadKey();
            }
        }
    }
}

Al ejecutar el código muestra el siguiente resultado


El ejemplo es sencillo para que pueda comprenderse creamos una clase EjConstructor con 2 variables enteras, luego definimos el constructor con 2 parámetros observen que tiene el mismo nombre de la clase eso tiene que ser así obligatoriamente, también tenemos un método Suma y un método resta que lo único que hace es realizar una suma y la resta sucesivamente.Luego en la clase Principal al momento de crear el objeto de la clase le pasamos los parámetros de una sola vez al constructor, y después solo imprimimos el resultado de la suma y la resta del método Suma y resta.

Ejercicios Resueltos de Constructores en C# 

Ejemplo 1

Realizar un programa que ingrese los sueldos de 5 operarios en un vector. Realizar la creación y carga del vector en el constructor.

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

namespace PruebaConstructor
{
    class Operarios
    {
        private int[] sueldos;

        public Operarios()
        {
            sueldos = new int[5];
            for (int f = 0; f < sueldos.Length; f++)
            {
                Console.Write("Ingrese el sueldo "+(f+1)+": ");
                string linea = Console.ReadLine();
                sueldos[f] = int.Parse(linea);
            }
        }

        public void Imprimir()
        {
            Console.WriteLine("Los Sueldos Ingresados.");
            for (int f = 0; f < sueldos.Length; f++)
            {
                Console.WriteLine(sueldos[f]);
            }
            Console.ReadKey();
        }

        static void Main(string[] args)
        {
            Operarios op = new Operarios();
            op.Imprimir();
        }
    }
}

Al ejecutar el código muestra el siguiente resultado


Explicación: 
Como la clase se llama Operarios el constructor tiene el mismo nombre, no disponemos la palabra clave void ya que el constructor no puede retornar datos.

La ventaja de plantear un constructor en lugar de definir un método con cualquier nombre es que se llamará en forma automática cuando se crea un objeto de esta clase:
            Operarios op = new Operarios();

Cuando se crea el objeto op se llama al método constructor.
Finalmente llamamos al método imprimir:
            op.Imprimir();

Ejemplo 2

Plantear una clase llamada Alumno y definir como atributos su nombre y su edad. En el constructor realizar el ingreso de datos. Definir otros dos métodos para imprimir los datos ingresados y un mensaje si es mayor o no de edad (edad >=18)

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

namespace PruebaConstructor
{
    class Alumno
    {
        private string nombre;
        private int edad;

        public Alumno()
        {
            Console.Write("Ingrese nombre:");
            nombre = Console.ReadLine();
            Console.Write("Ingrese edad:");
            string linea = Console.ReadLine();
            edad = int.Parse(linea);
        }

        public void Imprimir()
        {
            Console.WriteLine("Nombre:" + nombre);
            Console.WriteLine("Edad:" + edad);
        }

        public void EsMayorEdad()
        {
            if (edad >= 18)
            {
                Console.Write(nombre + " es mayor de edad.");
            }
            else
            {
                Console.Write(nombre + " no es mayor de edad.");
            }
        }

        static void Main(string[] args)
        {
            Alumno alumno1 = new Alumno();
            alumno1.Imprimir();
            alumno1.EsMayorEdad();
            Console.ReadKey();
        }
    }
}

Al ejecutar el código muestra el siguiente resultado



Explicación: 
En la main el constructor se llama en forma automática cuando creamos un objeto de la clase Alumno:
        static void Main(string[] args)
        {
            Alumno alumno1 = new Alumno();

Los otros dos métodos deben llamarse por su nombre y en el orden que necesitemos:
            alumno1.Imprimir();
            alumno1.EsMayorEdad();




¿Que es un destructor en c#?

DESTRUCTOR EN C#
  Un destructor es un método que se llama antes de finalizar la vida de un objeto. Se puede utilizar para afianzar ciertas operaciones que queremos que se realicen antes de destruir un objeto. Por ejemplo, se podría usar el destructor para asegurarnos que se cierra una conexión a una base de datos, o que se cierra un archivo abierto del objeto en cuestion.

  El formato general de un destructor es el siguiente:

~nombre_clase() {
  // Código del destructor.
}

  La tilde ~ se puede representar teniendo pulsada la tecla ALT y escribiendo a continuación los número 126.nombre_clase es el nombre de la clase, evidentemente.

CLR - Garbage Collection

  Una de las responsabilidades del CLR (Common Language Runtime) es la de proporcionar la gestión automática de la duración completa de los objetos en el entorno .NET FrameWork. Vaya... ¿y qué significa esto? Bien. Como se habrá podido observar, cuando creamos un objeto a partir de una clase, utilizamos la palabra clave new. Esta palabra lo que hace es asignar dinámicamente memoria para el nuevo objeto, devolviendo una referencia para poder encontrarlo. Hasta aquí todo normal. Pero si os fijáis, en ningún momento he incluido en los ejemplos escritos una instrucción para desalojar la memoria, esto es, no he destruido manualmente el objeto para liberar la memoria. Así en C está Malloc ó Calloc y free, en Pascal ó Modula-2 está el New y Dispose (creo recordar, hace muchos años que no programo en este maravilloso lenguaje) ó PowerBuilder con su Create y Destroy.

  Una de las grandes comodidades, de verdad, que me he encontrado a la hora de estar estudiando esta herramienta, y que nos va a ahorrar horas de trabajo, es el Garbage Collection ó recolección de elementos no utilizados. ¿Y qué es esto? Es un sistema que recopila objetos automáticamente (en segundo plano, de forma transparente, sin que sea necesaria la intervención del programador!). El funcionamiento es el siguiente: cuando no existe ninguna referencia a un objeto, se supone que el objeto ha dejado de ser necesario, y la memoria ocupada por él se libera. Esta memoria reciclada se puede utilizar para una asignación posterior.

  Esto quiere decir que nos tenemos que despreocupar de liberar memoria de forma manual, con la tranquilidad que eso conlleva.

Pequeño inciso: Cuando estaba estudiando en la Universidad, en las primeras prácticas de C bajo Linux (año 1.999, mas menos), se nos decía que este sistema operativo era muy bueno, que rara vez se colgaba... Bueno, el caso es que mi primera práctica programando en C, la compilaba, la ejecutaba, y ...crash, el Linux se colgaba!!!!. Después de destrozarme la cabeza, hice una pequeña investigación. Hice un grep de malloc y un grep de free en los ficheros fuentes. Tenía 67 mallocs y 2 free... Aquí aprendí la importancia de liberar memoria.... y al final aprobé y todo!!!!

NOTA IMPORTANTE: El método DESTRUCTOR siempre se llama antes que el Garbage Collection tenga lugar.

  A continuación vamos a ver un ejemplo sencillo para dejar claro los conceptos de destructor y constructor, así como la limpieza automática de memoria. El código es el siguiente:

/*

        Autor: ANGELOIDE
        PROGRAMA: ejemplo5.cs
        OBSERVACIONES: Clases en C# - Constructor, destructor y memoria
        FECHA: 01/07/2009

*/

using System ;

class clase_numero {
  // Definición del constructor.
  public clase_numero(int id) {
    ii_numero = id ;
  }

  // Definición del destructor.
  ~clase_numero() {
    Console.WriteLine("Destruyendo objeto " + ii_numero) ;
  }

  // Definición de variables de instancia.
  private int ii_numero ;

  // Definición de métodos.
}

class Ejemplo5 {
  // Procedimiento principal.
  public static void Main() {
    // Definimos varios objetos a partir de una clase mediante un bucle for.
    int i ;
    for (i = 1 ; i < 10 ; i++) {
      // Creamos el objeto con identificador i.
      clase_numero objeto_numero = new clase_numero(i) ;

      // Mostramos por pantalla el identificador de objeto.
      Console.WriteLine("Creado objeto con id " + i)  ;
    }

  }
}


  El resultado, como siempre, una vez compilado y ejecutado, es el siguiente:



  ¿Y qué es lo que hace este programa? Vamos por partes. En general lo que hace este programita es crear 10 objetos instanciados de la clase clase_numero y decir por pantalla que se han creado. ¿Cómo lo hacemos? Darse cuenta que en el constructor podemos inicializar el valor de la variable privada ii_numero (mediante el paso de un parámetro). Pues bien , creamos 10 objetos seguidos mediante un bucle for que hay en el cuerpo del Main. Para cada valor de i, vamos creando un objeto, de manera que más abajo escribo en la consola el id del objeto que es. La sintáxis del bucle for utilizado aquí es la siguiente:

 for (Inicialización de i ; Condición para que se cumpla el cuerpo del bucle ; Incremento de la variable i) {
  // Cuerpo del bucle.
}

No os preocupéis ahora por la sintaxis de estas estructuras de control. Se verá más adelante. Lo importante es quedarse con el otro concepto.

  i++ lo que hace es evaluar i y luego incrementar en 1 el valor de i. Esto se verá también mas adelante.

  Una vez que los objetos dejan de ser referenciados, se eliminan automáticamente. ¿Cómo lo sabemos? Porque se ejecuta el método destructor, el cual escribe por pantalla qué objeto está a punto de ser destruido. Recordar que inmediatamente después del método destructor viene el sistema de recolección de elementos no utilizados, que es el que libera memoria.

  El ejemplo no tiene mucho más que comentar, ya que el código lo dice todo. Espero que os haya aclarado los conceptos de constructor, destructor y liberación de memoria automática.