петак, 18. децембар 2015.

Konstruktori i destruktori u C# programskom jeziku


Iako sam samo spominjao konstruktore u postu „Klase u C# programskom jeziku“, vreme je da se napiše nešto više o konstruktorima ali ujedno i da se upoznate sa destruktorima. Constructor - konstruktor je najjednostavnije rečeno prva metoda koja se izvršava kad se poziva vaša klasa, stručnije rečeno kad se stvara primerak tipa. Svaka klasa ima konstruktor čak iako ga vi ne napišete i svaki konstruktor se u C# programskom jeziku zove isto kao i klasa. Znači konstruktor je specijalna metoda. Za programere Visual Basic-a to nije tako jer se u Visal Basic-u konstruktori prave potprogramom Sub New() dok sve ostalo uglavnom vezano za konstruktore važe ista pravila. Konstruktori jesu specijalna metoda, više metoda koja ne vraća vrednost ali bez ključne reči void jer konstruktori nikada ne mogu da vraćaju vrednosti. Konstruktori služe da vi inicijalizujete podatke klase ili strukture pre upotrebe. Ali konstruktori mogu biti redefinisani da bi obezbedili namensku funkcionalnost.

 
( Konstruktori se često simbolizuju sa građevinskim konstrukcijama )

Svaka klasa ili struktura može imati jedan konstruktor, čak iako ga ne napišete ili možete imati više konstruktora, ali svi se oni zovu isto kao i klasa. Međutim, da bi se konstruktori razlikovali jedan od drugog oni moraju da imaju različite atribute. Sintaksa za konstruktor je sledeća:

public bool ime_promenjive;
public class ime_klase
{
          public ime_klase( bool ime_atributa )

          { 
                     ime_promenjive = ime_atributa; 

          }
}


Možete pomisliti da u navedenoj sintaksi postoji greška, da sam trebao napisati ime konstruktora, ali jednostavno ime konstruktora nije opcija, već kao što je rečeno ime konstruktora mora biti isto kao i ime klase. Ukoliko naletite na ovakvo pitanje u Microsoft testovima, sa ovakvom opcijom; odgovor bi morao biti tačan inače i ime konstruktora je takođe tačan odgovor.

Kako se koriste konstruktori u kodu?



Najbolje da prvo pogledate kod sledećeg programa Constructors koji sadrži dve javne klase. MyBaseClass ima prazan konstruktor i konstruktor koji zahteva atribut tipa integer. Auto properti ima inicijalizovanu vrednost 100 kao defaultnu vrednost što je nova osobina u C# verziji 6.0. U ranijim verzijama C#-pa ne možete inicijalizovati auto propertije. Klasa MyDerivedClass nasleđuje klasu MyBaseClass ali tako takođe nasleđuje i koristi konstruktore klase MyBaseClass. To smo definisali sa ključnom rečju base što znači da klasa koristi konstruktor bazne ili roditelj klase. Klasa MyDerivedClass pored toga što koristi konstruktore bazne klase ima i jedan svoj konstruktor koji zahteva atribut tipa string. Program Constructors inicijalizuje 3 objekta koji koriste MyDerivedClass i svaki od njih poziva drugačiji konstruktor.

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

namespace Constructors
{
    public class MyDerivedClass: MyBaseClass
    {

        public string StringNumber { get; set; }

        public MyDerivedClass():base()
        {

        }

        public MyDerivedClass(int number):base()
        {
          
        }

        public MyDerivedClass(string number)
        {
            StringNumber = number;
          
        }
        
    }
}

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

namespace Constructors
{
    public class MyDerivedClass: MyBaseClass
    {

        public string StringNumber { get; set; }

        public MyDerivedClass():base()
        {

        }

        public MyDerivedClass(int number):base()
        {
          
        }

        public MyDerivedClass(string number)
        {
            StringNumber = number;
          
        }
        
    }
}

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

namespace Constructors
{
    class Program
    {
        static void Main(string[] args)
        {
            bool correct = false;
            uint number = 0;
            int? message = null;

            do
            {
                Write($"Enter an number from 1 to {Int32.MaxValue}: ");
                correct = UInt32.TryParse(ReadLine(), out number);

            } while (!correct || number < 1);

            MyDerivedClass EmptyConstructor = new MyDerivedClass();

            WriteLine(Environment.NewLine + "This call empty constructor that returns to the default value: ");
            message = EmptyConstructor?.Number;
            WriteLine(message);
            EmptyConstructor = null;
                     
            MyDerivedClass IntegerConstructor = new MyDerivedClass();
            IntegerConstructor.Number = (int)number;

            WriteLine(Environment.NewLine + "This call constructor that returns integer value: ");
            message = IntegerConstructor?.Number;
            WriteLine(message);
            IntegerConstructor = null;

            MyDerivedClass StringConstructor = new MyDerivedClass(number.ToString());

            WriteLine(Environment.NewLine + "This call constructor that returns string value: ");
            string messageString = StringConstructor?.StringNumber;
            WriteLine(messageString);
            StringConstructor = null;

            ReadKey();

        }
    }
}

Navedeni kod programa vam takođe pokazuje da više objekata može da instancira jednu klasu. Iako ovaj program nema tu potrebu; on vam takođe demonstrira kako se objektima dodeljuje null referenca. U programiranju treba da imate naviku da svakom objektu dodelite null referencu kad vam taj objekti više ne treba. Međutim kad koristite null vrednosti, neophodno je i da proveravate objekte da li neki objekat ima null referencu pre upotrebe objekta ili će te dobiti grešku. U C# verziji 6.0 najnovijim Elvis operatorom ?. mnogo jednostavnije proveravate da li objekat sadrži null vrednost. Kad pokrenete navedeni program, rezultat će biti sličan u zavisnosti koji ste broj uneli.

Enter an number from 1 to 2147483647: 5000

This call empty constructor that returns the default value:
100

This call constructor that returns integer value:
5000

This call constructor that returns string value:
5000


Kako izgleda navedeni program možete pogledati i na video-u:



( C# 6.0 Tutorial - Fundamentals - 25. Constructors )

Šta je destruktor?

Kao i konstruktor, destruktor je specijalna metoda koja služi za čišćenje resursa memorije. Za razliku od konstruktora, koji se kao metoda uvek izvršava prva, destruktor je specijalna metoda koja se uvek izvršava zadnja. Iskusni C++ programeri često koriste destruktore, ne samo radi čišćenja resursa nego i za dobijanje informacija u procesu otklanjanja grešaka i izvršavanja drugih zadataka. Destruktore u C++ programskom jeziku možete pogledati ovde. Međutim u C# programskom jeziku, destruktori se mnogo ređe koriste. Razlog je zato što u .Net Framework okruženju u jeziku C# reference objekata uklanja sakupljač otpadaka. To podrazumeva da može doći do kašnjenja stvarnog brisanja objekata u odnosu na izlaženje reference van dometa.

 
( Proces kojim redom destruktor uništava klase u memoriji )

U Visal Basic-u destruktor je poznat kao finalizator, potprogram Sub Finalize() koji sadrži kod za čišćenje kada je klasa uništena, ali u C# programskom jeziku se destruktor piše sa istim imenom klase ali sa znakom tilda ~ ispred metode. Sintaksa za destruktora u C# programskom jeziku je sledeća:

class ime_klase 
{
            ~ ime_klase()
           {

           }
}


Najvažnija stvar koju trebate da znate za destruktore je da njih ne možete definisati u strukturama, nego samo u klasama. Svaka klasa može imati samo jedan destruktor. Destruktori se ne mogu nasleđivati niti preopterećivati. Ne mogu se ni pozivati jer se sami automatski pozivaju i destruktori ne mogu imati niti modifikatore niti parametre. I još jedan savet. Nemojte nikad pisati prazne destruktore.

Kako se koristi destruktor u kodu?

Pogledajte kod programa Destructor koji je sastavljen od 3 klase. Klasa SecondClass nasleđuje klasu FirstClass dok klasa ThirdClass nasleđuje klasu SecondClass. Na taj način inicijalizacijom samo treće klase ThirdClass u programu se koriste sve tri klase. Jedna klasa može da nasledi samo jednu klasu. Svaka od navedenih klasa sadrži po jedan konstruktor i po jedan destruktor. Inicijalizacijom treće klase se automatski pozivaju sva 3 konstruktora u sve 3 klase. Kad korisnik pritisne bilo koji taster, objekat se inicijalizuje na null vrednost. Pozivom GC – Garbage Collector-a; aktiviraju se destruktori sve 3 klase.

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

namespace Destructor
{
    public class FirstClass
    {
       public FirstClass()
        {
            WriteLine("Creating first class!");

        }

        ~FirstClass()
        {
            WriteLine("Destroying first class!");

        }
    }
}

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

namespace Destructor
{
    class SecondClass : FirstClass
    {
        public SecondClass()
        {
            WriteLine("Creating second class!");

        }

        ~SecondClass()
        {
            WriteLine("Destroying second class!");

        }
    }
}

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

namespace Destructor
{
    class ThirdClass: SecondClass
    {
        public ThirdClass()
        {
            WriteLine("Creating third class!");

        }

        ~ThirdClass()
        {
            WriteLine("Destroying third class!");

        }
    }
}

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

namespace Destructor
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("Start...");

            ThirdClass myclass = new ThirdClass();

            WriteLine("--------------------");
            WriteLine("Object created!" + Environment.NewLine);
            WriteLine("Press any key to destroy it.");
            ReadKey();

            WriteLine("--------------------");
            WriteLine("Clean...");

            myclass = null;
            GC.Collect();
               
            ReadKey();

        }
    }
}

Kad pokrenete navedeni program rezultat će biti ovakav:

Start...
Creating first class!
Creating second class!
Creating third class!
--------------------
Object created!

Press any key to destroy it.
--------------------
Clean...
Destroying third class!
Destroying second class!
Destroying first class!


Kako izgleda navedeni program možete pogledati i na video-u:

 
( C# 6.0 Tutorial - Fundamentals - 26. Destructors )