1. Din nou despre operatorul new
- Forma generala este
new nume_clasa(lista_parametri);
unde nume_clasa determina numele clasei, realizata sub forma de exemplar al obiectului sau. Dar nume_clasa urmat de paranteze reprezinta constructorul acestei clase. Daca in clasa nu este determinat un constructor propriu, atunci in operatorul new va fi folosit consructorul oferit de C#. Prin urmare operatorul new poate fi folosit pentru crearea obiectelor, apartinind claselor de diferite tipuri.
- Memoria operativa este limitata si deaceia este posibila ca operatorul new nu va reusi sa aloce memorie pentru obiectul din cauza insuficientei de memorie operativa. In acest caz are loc situatia de excludere in timpul executarii programei.
2. Folosirea operatorului new impreuna cu tipul de date
- In legatura cu cele expuse mai sus apare intrebarea: de ce operatorul new nu se recomanda de folosit la variabilele de tip int sau float? In C# variabila tipului valorii contine valoare proprie. Memorie pentru pastrarea acestei valori se aloca automat in timpul rularii programei. Prin urmare nu este sens de alocat memorie cu operatorul new.
Pe de alta parte , in variabilele de tip referinta se pastreaza referinta la obiect, si deaceia memorie pentru pastrarea acestui obiect trebuie sa fie alocata dinamic in timpul executarii programei.
datorita faptului ca principalele tipuri de date (int, char, ...) nu se convertesc la tiul referinta, se mareste productivitartea programei. La folosirea tipului referinta exista un nivel de tangentialitate, care duce la intirzierea accesului la fiecare obiect. Acest nivel de tangentialitate se inlatura la folosirea tipului valoric.
- Operatorul new totusi se poate de folosit impreuna cu tipul valoric:
int i = new int();
In acest caz pentru tipul int se apeleaza constructorul, care initializeaza by default variabila i cu valoarea zero.
EX.:
/*
folosire operator new impreuna cu tipul valoric
*/
using System;
//folosire constructor cu parametri ai clasei Building
namespace NewValue
{
class Program
{
static void Main(string[] args)
{
int i = new int(); // initializare variabila i cu baloarea zero
Console.WriteLine("Valoarea variabilei i este: " + i);
Console.ReadKey(true);
}
}
}
Executarea acestei programe are rezultatul: Valoarea variabilei i este: 0
- Dupa cum arata si rezultatul executarii acestei programe, variabila i este initializata cu zero. Amintim,ca daca nu folosim operatorul new, variabila i va ramine neitinializata. Acest lucru poate genera erori al apelul variabilei i in operatorul, care contine metoda Writeline();, daca in prealabil nu i se atribie o valoare.
- In general adresarea la operatorul new pentru orice tip de date duce la apelul constructoului, folosit by default pentru tipul dat. Dar in acest caz memoria nu se aloca dinamic. In programare nu se foloseste operatorul new impreuna cu un tip de date valoric.
3. "Colectarea gunoiului" si folosirea desrtructorului
- La folosirea operatorului new memoria libera pentru crearea obiectelor, se imprateste dinamic. Desigur ca memoria operativa este limitata, si de aceia uneori se termina. Acest lucru poate duce la executarea eronata al operatorului new, din cauza lipsei de memorie pentru crearea obiectului. Anume din aceasta cauza un din principalele functii ale schemei de alocare a memoriei este eliberarea memoriei de obiectele nefolosite, pentru a ooferi altor obiecte. In multe limbaje de programare eliberearea memoriei se face manual (delete in C++). In C# se foloseste alt mod (mai sigur): "colectarea gunoiului"
- Sistema de "colectare a gunoiului" in C# elibereaza memoria de obiectele de prisos automat, actionind neobservata si fara implicarea programatorului. ''Colectarea gunoiului" are loc in modul urmaotr: Daca nu exista referinte laobiect, atunci acest obiect se considera nefolositor si memoria ocupata de el este eliberata. Aceasta memorie se foloseste ulterior pentru alte obiecte.
- "Colectare a gunoiului" se petrece periodic in timpul execitarii programei. Prin urmare nu putem sti cind se va produce acest lucru.
4. Destructorii
- In C# este posibilitatea de a determina o metoda , care se va apela inaintea distrugerii finale a obiecvtului sistemului de "colectarea a gunoiului". Aceasta metoda se numeste destructor si poate fi folosita in unele cazuri speciale, pentru a garanta sigur ca un obiect sia terminat activitatea. De exemplu desctructorul poate fi folosit pentru garantarea aliberarii resurselor de sistem, ocupate de obiectul corspunzator, Destructorul este o metoda destul de specifica, care se foloseste in cazuri rare si deosebite. Si dupa regula destructorii nu trebuiesc
- Forma generala a destructorilor
~nume_clasa() {
// codul destructorului }
unde nume_clasa este numele clasei concrete. Prin urmare, destructorul de declara asemanator constructorului, doar ca in fata destructorului se plaseaza "tilda(~)".Destructorului ii lipseste tipul returnat si argumentele.
- Pentru a adauga un destructor in clasa, este suficienta de -l inclus in calitate de membru al clasei. El se apeleaza ori de cite ori, cind se va folosi on obiect al clasei resprective. In destructor se pot indica actiuni care gvor fi efectuate inainte de a se distruge un obiect.
- Trebuie de mentiona ca destructorul se apeleaza inainte de "colectarea gunoiului". Nu se apeleaza,de exemplu, in acel moment, cind variabila care contine referinta la obiect, se afla in afara zonei de actiune al obiectului. Acest lucru inseamna ca, nu se poate de stiut din timp cind anume se va apela destructorul. In afara de asta programa se poate finaliza inainte de "colectarea gunoiului", si destructorul sa nu fie apleat de loc.
- Un exemplu de folosire al destrucorului. In aceasta programa se creaza si se distrug mai multe obiecte. Intr-un moment al acestui proces se va activa "colectarea gunoiului" si se apleaza destructorii pentru distrugerea obiectelor nefolositoare.
/*
folosire destructor
*/
using System;
class Destruct {
public int x;
public Destruct(int i) { x = i; }
//se apleaza la utilizarea obiectului
~Destruct() { Console.WriteLine("Distrugere " + x); }
//creaza obiect si automat il distruge
public void Generator(int i) { Destruct o = new Destruct(i); }
}
namespace DestructDemo
{
class Program
{
static void Main(string[] args)
{
int count;
Destruct ob = new Destruct(0);
/*Acum se vor crea mai multe obiecte
intr-un moment se va intimpla "colectarea gunoiului".
Pentru a activa "colectarea gunoiului este posibil
* ca va trebuie de marit numarul obiectelor create"*/
for (count = 1; count < 100000; count++)
ob.Generator(count);
Console.WriteLine("Sfirsit");
Console.ReadKey(true);
}
}
}
Aceasta programa lucreaza in felul urmator. Constructorul initializeaza variabila x. In acest exemplu variabila x serveste in calitate de identificator al obiectlui.Iar destrucotul afiseaza valorile variabilei x, cind obiectul se utilizeaza. Interese deosebit prezinta metoda Generator(), care creaza si distruge obiectele de tip Destruct. Initial in clasa DestrucDemo se creaza obiectul initial ob de tip Destruct., pe urma are loc crearea si distrugerea a 100 mii de obiecte. indiferite momente ale acestui proces are loc "colectarea gunoiului". Densitatea acestui lucru depinde de mai multi factori,: de volumul de memorie libera initial, SO,etc. Intr-un moment incep sa se afiseze mesajele formate de destructor.
- Inca un moment important: metoda WriteLine() este apelata in destructorul ~Destruct() exclusiv pentru a demonstra acest exemplu. Destructorul trebuie sa actioneze doar asupra variabilelor exemplarului determinate in clasa sa.
5. Cuvibntul cheie this
- Cind metoda se apeleaza automat i se transmite o referinta la obiectul apelat. Aceasta referinta se numeste this si determna anume acel obiect, la care se actioneaza aceasta metoda
- Pentru a exemplifica vom crea clasa Rect, care incapsuleaza latimea si inaltimea dreptunghiului si contine metoda Area(), care returneza suprafata dreptunghiului:
using System;
class Rect {
public int Width;
public int Height;
public Rect (int w, int h){Width = w; Height = h;}
public int Area(){return Width * Height;}
}
namespace UseRect
{
class Program
{
static void Main(string[] args)
{
Rect r1 = new Rect(4, 5);
Rect r2 = new Rect(7, 9);
Console.WriteLine("suprafata dreptunghiului r1: " + r1.Area());
Console.WriteLine("suprafata dreptunghiului r2: " + r2.Area());
Console.ReadKey(true);
}
}
}
Dupa cumne este cunoscut, alti membri ai clasei pot fi accesati direct fara indicarea adaugatoare al numelui obiectului sau clasei. De aceia operatorul
return Width * Height
Din metoda Area() inseamna, ca copii ale variabilelor Width si Height, aflate in legatura cu obiectul apelat, vor fi inmultiti, iar metoda va returna rezultatul inmultyirii. Acekasi operator se poate de scris si asa
return this.Width * this.Height;
In acest operator cuvintul cheie this inseamna obiect, pentru care este apelata metoda Area().Prin urmare, in expresia this.Width se face referinta la copia variabilei Width al acestui obiect, iar expresia this.Height - referinta la copia variabilei Height al aceluiasi obiect. Asa dar, daca metoda Area() a fost apelata pentru obiectul x, atunci cuvintul cheie this in operatorul prezentat mai sus, ar fi insemnat referinta laobiectul x. Scrierea operatorului fara cuvintul chei this in exemplul de mai sus reprezinta o forma prescurtata a scrieirii.
- Cuvintul cheie this se poate de folosit si in constructor. In acest caz el determina un obiect, care se construieste. De exemplu urmatorii operatori ai metodei Rect()
Width = w;
Height = h;
se putea a fi scri asa
this.Width = w;
this.Height = h;
Asa metoda de scriere in acest caz nu da nici un fel de prioritate. pentru a exemplifica vom mnodifica clasa Rect, folosind cuvintul cheie this:
using System;
class Rect {
public int Width;
public int Height;
public Rect (int w, int h){
this.Width = w;
this.Height = h;
}
public int Area(){
return Width * Height;
}
}
namespace UseRect
{
class Program
{
static void Main(string[] args)
{
Rect r1 = new Rect(4, 5);
Rect r2 = new Rect(7, 9);
Console.WriteLine("suprafata dreptunghiului r1: " + r1.Area());
Console.WriteLine("suprafata dreptunghiului r2: " + r2.Area());
Console.ReadKey(true);
}
}
}
- cuvintul cheie this nu se foloseste ca in programul de mai sus, pentru ca nu da nici un efect practic. Cu toate acestea cuvintului cheie this i se poate de gasit intrebuintare folositoare. De exemplu, in sintaxa C# se permite de denumit parametrul sau variabila locala cu acelas nume, ca si variabila exemplarului. In acest caz numele variabilei locale acopera numele variabila exemplarului. Pentru acces la variabila ascunsa a exemplarului va fi folosit cuvintul cheie this.
Ex.:
public Rect (int Width, int Height){
this.Width = Width;
this.Height = Height;
}
In aceasta varianta de scriere al construcorului Rect() numele parametrilor sunt aceleasi ca si numele variabilelor exemplarului, si prin urmare, le acopera. Dar pentru a "depista" variabilele ascunse vom folosi cuvintul cheie this.