Sunteți pe pagina 1din 83

Programare Microsoft

Visual Studio .NET


Note de curs

Version no.: 2

Page 1 of 83

Cuprins
1

INTRODUCERE......................................................................................................................................................4

PROGRAMARE ORIENTAT OBIECT (POO).................................................................................................7


2.1
INTRODUCERE.....................................................................................................................................................7
2.1.1
Ce este POO?.............................................................................................................................................7
2.1.2
Ce este un obiect?......................................................................................................................................7
2.1.3
Ce este o clas?..........................................................................................................................................7
2.2
CREAREA APLICAIILOR POO N MEDIUL DE DEZVOLTARE MICROSOFT VISUAL STUDIO.................................9
2.2.1
Crearea proietelor de tip "Console Application".......................................................................................9
2.2.2
Seciunile unui proiect creat n VS.............................................................................................................9
2.2.3
Adugarea de noi clase n VS..................................................................................................................10
2.2.4
Lansarea n execuie a proiectelor...........................................................................................................11
2.3
ARHITECTURA CLASELOR N POO....................................................................................................................12
2.3.1
Elementele componente ale unei clase.....................................................................................................12
2.3.1.1

Declararea variabilelor n POO............................................................................................................................13

2.3.2
Analiza clasei "Person"...........................................................................................................................13
2.3.3
Instantierea Claselor................................................................................................................................14
2.3.4
Constructori. Overloading.......................................................................................................................14
2.3.5
Domeniul de vizibilitate pentru componentele unei clase........................................................................16
2.3.6
Domenii de vizibilitate pentru o clas.....................................................................................................17
2.4
CONCEPTELE PROGRAMRII ORIENTATE OBIECT.............................................................................................18
2.4.1
Abstractizare............................................................................................................................................18
2.4.1.1

2.4.2
2.4.2.1
2.4.2.2

2.4.3
2.4.3.1
2.4.3.2
2.4.3.3
2.4.3.4
2.4.3.5

Referina obiectelor.............................................................................................................................................18

Incapsulare...............................................................................................................................................19
Conceptul de ncapsulare.....................................................................................................................................19
Interfaa clasei Person..........................................................................................................................................19

Motenirea................................................................................................................................................21
Conceptul de motenire.......................................................................................................................................21
Suprascriere (override)........................................................................................................................................23
Identificatorii this i "base".............................................................................................................................24
Metode i variabile statice...................................................................................................................................26
Clase abstracte.....................................................................................................................................................28

2.4.4
Polimorfismul...........................................................................................................................................28
2.5
ASPECTE ALE POO N MEDIUL DE DEZVOLTARE MICROSOFT VISUAL STUDIO................................................30
2.5.1
Garbage collection...................................................................................................................................30
2.5.1.1
2.5.1.2

2.5.2
3

Eliberarea memoriei n mod automat...................................................................................................................30


Eliberarea memoriei la cerere..............................................................................................................................31

Excepii i tratarea excepiilor.................................................................................................................32

DEZVOLTAREA APLICAIILOR DE TIP GUI IN VS.NET..........................................................................35


3.1
ETAPELE DEZVOLTRII UNEI APLICAII WINDOWS N VS.NET........................................................................35
3.2
PRIMA APLICATIE WINDOWS: "HELLO WORLD"................................................................................................36
3.2.1
Funcia InitializeComponent....................................................................................................................40
3.2.2
Interceptarea evenimentelor.....................................................................................................................40
3.2.2.1
3.2.2.2

Evenimente i delegai. Soluii cu proiecte multiple............................................................................................42


Handlere multiple................................................................................................................................................45

3.2.3
Concluzii..................................................................................................................................................46
3.3
UTILIZAREA CONTROALELOR STANDARD N VS.NET.....................................................................................48
3.3.1
Controlul TextBox.....................................................................................................................................48
3.3.1.1

3.3.2
3.3.3
3.3.4
3.3.5

Validarea informaiilor din TextBox....................................................................................................................50

Controlul ToolTip.....................................................................................................................................50
Controlul CheckBox (caseta de validare)................................................................................................51
Controlul RadioButton (buton radio).......................................................................................................51
Controlul ComboBox (list ascuns).......................................................................................................53

Version no.: 2

Page 2 of 83

SALVAREA DATELOR DE LUCRU...................................................................................................................55


4.1
SALVAREA DATELOR N FIIER...........................................................................................................................55
4.1.1
Citirea datelor din fisier...........................................................................................................................56
4.2
SERIALIZARE.....................................................................................................................................................57
4.2.1
Salvarea informaiilor n clasa Student...................................................................................................57
4.2.2
Serializarea clasei Student.......................................................................................................................57
4.3
SALVAREA INFORMAIILOR N BAZE DE DATE...................................................................................................62
4.3.1
Ce este o baz de date..............................................................................................................................62
4.3.2
Instalarea bazei de date...........................................................................................................................63
4.3.3
Crearea tabelelor.....................................................................................................................................63
4.3.4
Salvarea obiectului "Student" n baza de date.........................................................................................66
4.3.4.1
4.3.4.2
4.3.4.3

4.3.5
5

Tehnologia ADO.NET.........................................................................................................................................66
Stabilirea conexiunii la baza de date....................................................................................................................67
Funcia de salvare a obiectului "Student" n baza de date....................................................................................68

Afisarea dinamic a mesajelor. Controalele StatusStrip i Timer............................................................70

APLICAIA "E-STUDENT"................................................................................................................................72
5.1
COLECII DE OBIECTE.......................................................................................................................................72
5.2
CITIREA LISTELOR DE STUDENI DIN BAZA DE DATE........................................................................................73
5.3
FORMA "E-STUDENT".......................................................................................................................................74
5.3.1
Afiarea anilor universitari......................................................................................................................74
5.3.2
Afiarea grupelor.....................................................................................................................................75
5.3.3
Popularea automat a listelor de tip ComboBox.....................................................................................77
5.3.4
Afiarea studenilor. Controlul DatGridView...........................................................................................77
5.3.5
Interceptarea evenimentelor date de grid................................................................................................80
5.3.6
Inscrierea studenilor n grupe.................................................................................................................83
5.3.7
Conectarea aplicaiei la diverse tipuri de baze de date...........................................................................85

BIBLIOGRAFIE....................................................................................................................................................87

Version no.: 2

Page 3 of 83

1 Introducere
Hello world ... probabil este cel mai des utilizat exemplu cnd se ncepe un nou curs de programare. Acest
Hello world a fost introdus de Brian Kernighan n 1974 cnd a scris prima carte de programare n limbajul
C. Cine nu cunoate (sau mai bine zis, care programator nu cunoate) celebrul exemplu de la care a pornit
era limbajelor de programare de nivel nalt?
int main()
{
printf("hello, world");
return 0;
}
De fapt acest program demonstra ce simplu este n noul limbaj C s afiezi un text pe ecran. Era o mare
realizare la vremea aceea, s scrii un text pe ecran ntr-un mod att de simplu. De ce era o mare realizare?
Pentru c, nainte de a aprea acest C, lumea programa n limbaj de asamblare. Limbajul de asamblare
este limbajul pe care-l nelege microprocesorul. Si nu este un limbaj foarte evoluat, microprocesorul este
un circuit integrat care nelege i poate executa un set limitat de instruciuni. Tot ce tie s fac
microprocesorul se restrnge la o serie de operaii de adunare, scdere (bine, acum tie s fac i nmuliri
n virgul mobil pentru c are procesorul matematic ncorporat), ncrcare de regitri, citire/scriere din
memorie. De exemplu, pentru a face o adunare banal de 2+3, lucrnd direct cu microprocesorul, ar trebui
s facem urmtorul progrmel:
LD
ADD
LD

A,2
; incarca in registrul A numarul 2
A,3
; aduna la valoarea din registrul A numarul 3, rezultatul se salveaza tot in A
(HL),A ; salveaza in memorie la adresa data de registrul HL continutul lui A

Paradoxal la prima vedere, calculatorul care tie s rezolve att de multe probleme i att de complicate, se
bazeaz pe un circuit ce nu cunoate dect operaii aritmetice. Si totui, orict de complicat ar fi o funcie,
aceasta se poate descompune ntr-o serie de operaii aritmetice (serie Taylor) care s poat fi executate de
microprocesor. De exemplu, funcia sin(x) pentru un x dat se poate calcula prin seria Taylor echivalent:

sin( x ) x

x3 x5

....
3!
5!

Unde x3 se calculeaz prin nmulirea de 3 ori a lui x cu el nsui, i tot aa.


Concluzia este c, orice problem trebuie mprit ntr-un ir de operaii mici ce pot fi executate de
microprocesor. Aceast operaie de algoritmizare a unei probleme, mpreun cu scrierea codului echivalent
care s traduc taskurile rezultate ntr-un ir de instruciuni ce pot fi executate de microprocesor, se
numete programare.
Evident, nu trebuie mers cu despicatul problemei pn la nivelul de jos al microprocesorului, pentru c n
timp au aprut compilatoarele, sau mai bine zis limbajele de programare. Este clar c pentru un
programator este foarte dificil s reduc problema doar la un ir de operaii aritmetice, cum este la fel de
evident c microprocesorul nu poate mai mult. De aceea, s-a creat aceast interfa ntre programator i
microprocesor care s traduc operaii de nivel nalt (cu care lucreaz programatorul) ntr-un ir de operaii
mici la nivelul codului main. Folosind aceste limbaje de programare, programatorul nu mai este nevoit s
scrie LD A, 2 ...., ci scrie direct x=2+3, mult mai simplu i mai cite.
In plus, aceste limbaje vin cu o serie complex de biblioteci ce conin funcii gata facute care ne ajut s
rezolvm problema. De ce s m chinui eu s descompun funcia sin(x) n serie Taylor, cnd pot apela pur
i simplu funcia sin(x) din biblioteca matematic. Ar fi foarte dificil pentru mine s scriu un program care s
traseze o linie pe ecran, sau s scriu un text pe ecran. Ar trebui s tiu o mulime de detalii legate de
monitor, de adrese de memorie, modul de transmisie a informaiei la monitor, etc. Ca s trasez o linie, mi-ar
trebui o pagina de cod i zile bune de cercetare. Este mult mai simplu s apelez funcia lineto(x,y) din
biblioteca grafic, sau funcia printf() pentru a scrie un text pe ecran (mai retinei exemplul printf(hello
world) ?).

Version no.: 2

Page 4 of 83

Aceste limbaje de programare au evoluat continuu, de la revoluionarul la vremea respectiv, dar acum
banalul C, pn la sistemele Visual din zilele noastre n care programatorul scrie cod doar din operaii de
mouse.
Sunt o multitudine de limbaje de programare pe pia, fiecare avnd avantaje specifice pentru un anumit
domeniu de utilizare.
La nivelul de jos se situeaz limbajele de asamblare. Instruciunile acestor limbaje sunt apropiate
de modul de lucru al microprocesorului i foarte departe de modul nostru de a gndi o rezolvare la o
problem dat. O adunare banal de forma "val_total = val + val_TVA" se traduce n asamblare ntr-un set
destul de mare de instruciuni microprocesor mai puin inteligibile. Chiar dac la un moment dat limbajele de
asamblare erau la mod (unii chiar aveau sisteme multitasking dezvoltate n asamblare), astzi nu se mai
justific programarea n asamblare. Avantajele acestui sistem (viteza mare de execuie i consum redus de
memorie) nu mai reprezint un argument suficient de puternic n faa dezavantajelor evidente n
dezvoltarea aplicaiilor.
Imediat peste limbajul de asamblare sunt limbajele de programare clasice: C standard, Basic,
Pascal, Fortran, Cobol, etc. Au aprut din necesitatea unei interfee agreabile ntre programator i
microprocesor. Programeaz astzi cineva n limbaje clasice? Da, i nc foarte mult. S nu uitm c
majoritatea automatizrilor sunt realizate cu microcontrolere. Un microcontroler este un calculator n
miniatur: ntr-un singur circuit integrat este inclus microprocesorul, ceva memorie (512 octeti RAM, 2 KO
memorie FLASH, 1 KO EEPROM), mai sunt circuitele de intrare/ieire, convertoare AD/DA, circuite de
numrare/temporizare. n viaa de zi cu zi suntem nconjurai de aparate cu microcontroler: televizorul,
maina de splat automat, cuptorul cu microunde, autovehiculul etc. Toate aceste microcontrolere au n
dotare un compilator de C n care programatorul poate s dezvolte propriul algoritm de automatizare.
Totui, cnd este vorba de interfa grafic cu utilizatorul, limbajele clasice nu mai fac fa. Trebuie
s trecem la sisteme vizuale de programare: Visual C++, Visual Basic, Java, Lab View. Majoritatea
aplicaiilor de pe calculatorul dumneavoastr sunt construite ntr-un limbaj vizual. Ne-am obinuit att de
mult cu butoane, meniuri, ferestre, mouse, nct nu mai concepem s utilizm programe care s nu prezinte
asemenea faciliti.
Programarea ntr-un mediu vizual a schimbat n mod radical tehnica dezvoltrii programelor. S-a trecut la
programarea bazat pe evenimente. Programul nostru este format dintr-un numr de obiecte (butoane,
text-box-uri, datagrid-uri, liste ... ) , majoritatea luate din platforma de dezvoltare, altele construite de noi,
obiecte ce rspund la diverse evenimente transmise de sistemul de operare. Astfel, la o simpl micare a
mouse-ului pe ecran, sistemul de operare trimite zeci de mesaje MOUSE-MOVE obiectului deasupra cruia
se afl n acel moment mouse-ul. Se face click pe butonul mouse-ului, obiectul respectiv primeste mesajul
MOUSE-CLICK. Programul nostru nu face altceva dect s atepte mesajele i le trateaz pe acelea care
ne intereseaz. E clar ca dac vine un mesaj MOUSE-CLICK la un buton pe care noi am scris SAVE,
trebuie s scriem ceva cod care s rezolve acel eveniment i anume, s salvm ceea ce este de salvat n
acel context. Dar dac vin mesaje de tipul WM_SIZE (care ne atenioneaz c utilizatorul tocmai modific
mrimea obiectului), atunci lsm mesajul s mearg mai departe, nu-l interceptam. Mesajele
neinterceptate de aplicaia noastr sunt preluate de Windows care rezolv problema i redeseneaz
obiectul la mrimea corespunztoare.
Deci ce sistem de programare folosesc? Ultima tehnologie de programare Visual Studio .NET dezvoltat de
Microsoft reprezint n mod cert alegerea potrivit pentru majoritatea programelor de aplicaii. De mult timp
se ateapt o platform de programare n care s se poat dezvolta module n limbaje diferite, s ruleze pe
orice sistem, s nu aib probleme de compatibilitate cu diversele versiuni de DLL-uri i s aib un set
complet de controale Windows. Visual Studio .NET vine n ntmpinarea acestor cerine, anunndu-se ca
fiind sistemul de programare ce va fi utilizat n urmtorii ani.
Mai conteaz C sau Basic? Sub platforma .NET nu prea mai conteaz. Inainte, programatorii erau de acord
c, dac trebuie construit un proiect mare, acesta nu poate fi fcut dect n C++. Pentru proiecte mai mici
se utiliza Visual Basic care era mai uor de utilizat i avea o interfa mult mai agreabil. Acum, cele dou
limbaje au ajuns la acelai nivel, Basic-ul integrnd toate conceptele care erau apanajul C-ului (motenire,
multithreading), iar C-ul cptnd acea interfa agreabil cu care ne-a obinuit Basic-ul. Deci, alegerea
unui limbaj sau altul rmne doar o chestiune de gust.

Version no.: 2

Page 5 of 83

Si totusi, Microsoft a scos limbajul C#, un limbaj conceput de la inceput s funcioneze pe obiecte, deci el
implementeaz n mod nativ toate conceptele programrii pe obiect. Din acest motiv se consider ca C#
este alegerea potrivit pentru demararea unei aplicaii software complexe. Iar acest limbaj face i obiectul
cursului de fa.
Acest curs se adreseaz nceptorilor n domeniul programrii orientat obiect. Cititorul trebuie doar s aib
cteva noiuni simple de limbaj C (sau orice alt limbaj clasic) pentru a nelege conceptele definite aici.
Sunt prezentate la nceput cteva noiuni de baz ale programrii pe obiecte, noiuni pe care se bazeaz
orice program scris n aceast tehnic.
Se trece apoi la programarea aplicaiilor de tip "user interface" cu toate aspectele specifice: controale
vizuale, proprieti specifice, evenimente i tratarea evenimentelor.
O bun parte din curs trateaz modul de lucru cu bazele de date sau alte tehnici de salvare a datelor.
Aceasta deoarece, orice program mai serios n ziua de astzi are n spate o baz de date. Programele n
general lucreaz cu date i cel mai sigur mod de a menine coerena datelor l reprezint baza de date.
Toate noiunile sunt exemplificate prin programe concrete care se pun cap la cap n timpul derulrii cursului
astfel nct, la sfrit s avem o aplicaie funcional de o complexitate medie. In acest mod, cursul devine
mai puin plicticos, studentul avnd tot timpul posibilitatea s verifice i s adauge noi funcionaliti care i
se par interesante.
Cursul este de tip introductiv, avnd scopul deteptrii unui anumit interes fa de acest domeniu al
programrii. Programarea nu este o meserie grea (bine, poate fi i grea n anumite situaii), dar poate fi
extrem de interesant i atractiv dup ce ai trecut de primele obstacole ale nelegerii fenomenului.
Frumuseea deriv din faptul c tot ce ai nevoie ca s construieti o aplicaie, este un calculator i n orice
moment poi vedea rezultatele muncii tale n mod direct. Acest fapt i d ncredere i curaj s mergi mai
departe. Nu ai nevoie de maini unelte, materie prim, sau alte asemenea utiliti, ci doar de imaginaie,
optimism i chef de lucru. In rest, prin intermediul internetului, toat informaia necesar ii st la dispoziie.
Nu mai amintim faptul c este o meserie curat, unde se ctig destul de bine i cu care te poi angaja
oriunde n lume, fr a se ine seama de diferena tehnologic ntre ara unde ai nvat i ara unde lucrezi.

Version no.: 2

Page 6 of 83

Programare Orientat Obiect (POO)

2.1 Introducere
2.1.1 Ce este POO?
POO (OOP Object Oriented Programming) reprezint o metod, un concept de implementare a
programelor software. Dac n vechile limbaje de programare C, Pascal, structura unui program era
compus dintr-o succesiune de funcii ce se apelau ntre ele, un program construit n filozofia POO este
format dintr-o colecie de obiecte de sine stttoare ce interacionez ntre ele pentru ndeplinirea scopului
final.
Programarea orientat pe obiecte este metoda utilizat aproape exclusiv n momentul de fa n toate
domeniile tehnologiilor informaionale. Acest succes se datoreaz modului n care clasele i obiectele
definite ntr-un program orientat obiect emuleaz lumea real.
Astfel, orice obiect din lumea real (persoan, main, televizor, etc) se caracterizeaz prin dou
concepte:
proprieti: ( culoare, marc, tensiune de alimentare, salariu ) ce definesc componenta static
a obiectului;
funcii (metode): (schimb volum, deplaseaz, ...) prin care se modific comportamentul
obiectului.
In POO o colecie de obiecte de acelai tip formeaz o clas de obiecte. Clasele formeaz o ierarhie,
pornind de la o clas de baz ce reprezint o abstractizare simpl a realitii, la care, prin folosirea
conceptului de motenire se adaug pe rnd noi detalii specifice, ajungnd la clase mult mai complicate, ce
definesc ntr-un mod fidel obiectele reale. Acest mecanism de motenire a claselor prin formarea unor clase
derivate dintr-o clas de baz a permis o cretere considerabil a productivitii n programare, deoarece
toat munca inclus n clasa de baz se refolosete n clasa derivat.
De exemplu, pentru adugarea unui buton n aplicaia noastr, noi trebuie s instaniem un obiect
din clasa "Button". Aceast clas include proprieti i metode specifice unui buton:
Proprieti: culoare, lungime, lime, poziie, fontul de scriere, etc.
Funcii: Focus, GetHashCode, ToString, Click
Putem observa c multe din aceste metode aparin oricrei ferestre (Window) de uz general. Un Buton este
pn la urm o fereastr particularizat pe anumite funcii. De aceea este mult mai uor s folosim clasa
Window i s-i adugam cteva evenimente i funcii specifice unui buton (funcia ButtonClick de exemplu),
dect s construim clasa buton de la zero. Toate proprietile unei ferestre (culoare, poziie,..) se pstreaz
n noua clasa "Button" prin motenire, deci nu mai trebuie create de la zero.
La fel se motenesc din clasa Window i alte controale de tip GU (Graphic Interface): TextBox, ComboBox,
MessageBox, etc.

2.1.2 Ce este un obiect?


Un obiect poate fi considerat ca ceva real, concret, ce poate realiza anumite funcii. Multitudinea de
activiti ce pot fi executate de ctre un obiect definesc funcionalitatea obiectului (obiectul Button execut o
funcie cnd se face click pe el, obiectul de tip Window i modific dimensiunile cnd utilizatorul "trage" cu
mouse-ul de marginile acesteia).

2.1.3 Ce este o clas?


In termenii POO, un obiect este o instan a unei clase. Clasa reprezint o definiie a obiectului, un plan, un
tipar ce descrie funcionalitatea obiectului.
In cele ce urmeaz ne propunem s definim o clas simpl numita "Person" care s includ cteva din
atributele caracteristice unei persoane din lumea real: nume, prenume, data naterii. Pe baza acestei
definiii vom deriva alte dou clase care s conin noi atribute, dar de data aceasta specifice unui student

Version no.: 2

Page 7 of 83

i unui profesor. Studentul i profesorul reprezint persoane in primul rnd, deci sunt caracterizate de
nume, prenume, etc, dar au i atribute proprii domeniilor lor de activitate: bursier, ef de catedr, etc.

Version no.: 2

Page 8 of 83

2.2 Crearea aplicaiilor POO n mediul de dezvoltare Microsoft Visual


Studio
Pentru exemplificare i implementarea conceptelor legate de POO vom folosi mediul de dezvoltare
Microsoft Visual Studio 2008 (VS).

2.2.1 Crearea proietelor de tip "Console Application"


Primul pas ce trebuie fcut n realizarea unui program este s se creeze o nou soluie in VS, iar n cadrul
acestei soluii s se dezvolte diverse proiecte care puse cap la cap s rezolve taskul final (prin soluie
nelegem o colecie de proiecte ce colaboreaz pentru rezolvarea unui task).
Se deschide VS i se alege numele soluiei si al primului proiect pe care dorim s-l implementm:

Setm pentru soluie numele "OOP Course", iar primul proiect va fi "OOP Fundamentals". Foarte important,
alegem tiparul (template) acestui proiect de tip "Console Application". Este un tip simplu, ce permite
verificarea rapid a conceptelor de programare pe obiect.

2.2.2 Seciunile unui proiect creat n VS


Dup ce s-a selectat tipul de proiect, VS creeaz n mod automat structura soluiei i fiierele de nceput ale
proiectului:

Version no.: 2

Page 9 of 83

Observm proiectul OOP Fundamentals ce include cateva seciuni ntlnite n toate aplicaiile:
o Seciunea Properties unde se afl fiierul AssemblyInfo.cs. Acest fiier conine
informaii despre proiect: versiune, titlu, copyright, etc.
o Seciunea References: sunt incluse librriile utilizate in cadrul acestui proiect. Aici
putem adauga atat librrii din biblioteca VS.NET, cat i alte surse de cod: proiecte din
cadrul aceleeai soluii, sau fiiere DDL. Orice sursa extern de cod trebuie mai inti
adugat in seciunea References ca s poat fi vizibil i utilizat in cod.
o Clasa "Program": este clasa implicit a proiectului, punctul de intrare n program. Ca i
n limbajul C clasic, aici se gasete funcia Main() de unde va porni rularea aplicaiei. In
aceast funcie programatorul trebuie s adauge cod care s rezolve taskul proiectului.
o ClassDiagram si Person sunt fiiere adaugate de noi despre care vom vorbi n
continuare.

2.2.3 Adugarea de noi clase n VS


In continuare vom aduga o nou clas n proiect: click dreapta pe proiectul "OOP Fundamentals" i se
alege opiunea Add Class, numele noii clase va fi "Person":

Codul clasei "Person" este dat n continuare:

Version no.: 2

Page 10 of 83

Componena clasei Person se poate vedea mai bine dac se construiete diagrama acesteia. Click dreapta
pe clas i se alege opiunea "View Class Diagram":

2.2.4 Lansarea n execuie a proiectelor


Fiecare nou proiect creat n VS are o clas implicit numita "Program" ce conine funcia Main(), punctul de
lansare a programului.
Adaugm n aceast funcie cteva linii de cod care s creeze un obiect din clasa Person, definim numele,
prenumele i data naterii pentru obiectul creat i apoi se afieaz aceste informaii la consol:

Version no.: 2

Page 11 of 83

Dup completarea clasei Program se apas tasta F5 ce realizeaz urmtoarele taskuri n VS:
- salveaz toate fiierele din proiect ce au fost modificate
- compileaz, link-editeaz i construiete fiierul final "OOP Fundamentals.exe"
- lanseaz n execuie fiierul "OOP Fundamentals.exe" utiliznd modul de depanare a programului
(Debug). Acest mod de execuie permite inserarea de puncte de ntrerupere n program (Breakpoints) unde
utilizatorul poate accesa variabilele interne i analizeaz modul de execuie.
Programul se poate opri oricnd din execuie prin apsarea tastei SHIFT+F5.

2.3 Arhitectura claselor n POO


2.3.1 Elementele componente ale unei clase
Clasa Person creat mai sus este o clas foarte simpl, dar conine cele trei componente de baz a oricrei
clase:
Cmpuri (Fields): reprezint variabile interne ale clasei n care sunt stocate informaiile de lucru
curente. Aceste variabile pot avea diverse structuri, de la cele predefinite (int, long, double), pn la
structuri complexe definite prin intermediul altor clase.

Proprieti (properties): definesc interfaa static a clasei: seteaza sau furnizeaz valorile
variabilelor interne. Proprietile au dou seciuni ce lucreaz mpreun: get i set. Prima
furnizeaz valoarea catre exterior, iar prin set se modific din exterior valoarea variabilei interne.
Nu-i o regul obligatorie s existe ambele componente, pot exista cazuri ca o proprietate s fie
"read only" deci permite doar citirea variabilei.

In marea majoritate a cazurilor, o proprietate este doar o reflexie a variabilei interne in exterior. Nu se face
nici o procesare a informaiei in momentul trecerii valorii din exterior in interior sau invers.
De exemplu, n clasa Person exist proprietatea "BirthDate" ce nu face altceva dect s fac accesibil
valoarea _birthDate n exterior:
public DateTime BirthDate
{
get { return _birthDate; }
set { _birthDate = value; }
}
De aceea, se pot defini proprieti automate, la care VS creez automat un cmp n spate care s pstreze
valoarea setat prin proprietate:
public string Name { get; set; }

Version no.: 2

Page 12 of 83

Acest lucru ne salveaz de a scrie multe linii de cod, iar funcionalitatea este aceeai.
Observaie: Proprietatea nu face altceva dect s fac public valoarea variabilei interne. Acelai lucru se
obine dac se declar acea variabil drept "public", adic public in exterior. Totui, este o regul de bun
programare in OOP care spune c nu-i bine s faci publice componentele interne ale clasei, ci ntotdeauna
acestea trebuie expuse printr-o proprietate care s controleze accesul la acea component.
Avantajul utilizrii proprietilor se poate observa la proprietatea "BirthDateString":
public string BirthDateString
{
get { return _birthDate.ToString(dateTimeFormat,
CultureInfo.InvariantCulture); }
set { DateTime.TryParse(value, out _birthDate); }
}
In acest caz, variabila intern nu este expus direct la exterior, ci se face o conversie prealabil din formatul
DateTime n formatul ir de caractere.

Funcii (Methods): reprezint interfaa dinamic a clasei, prin intermediul crora clasa execut
anumite taskuri atunci cand sunt accesate din exterior.

Nu toate funciile pot fi apelate din exterior, sunt funcii de uz intern, vizibile doar n interiorul clasei.
Vizibilitatea unei funcii (sau n general, a oricrei componente) este dat de domeniul de vizibilitate setat
pentru acea component.

2.3.1.1 Declararea variabilelor n POO


Ca i n C clasic, orice variabil trebuie declarat nainte de a fi utilizat. Avantajul n C# este c putem
declara variabile n orice parte a programului, nu n mod neaprat la nceputul lui. Declararea unei variabile
presupune urmtoarele informaii:
- domeniul de vizibilittate (public, private, etc.)
- numele variabilei
- tipul (double, int, string, DateTime, etc.)

2.3.2 Analiza clasei "Person"


Clasa Person conine dou variabile interne:
_birthDate de tipul DateTime ce stocheaz data naterii pentru persoana respectiv. Este o
variabil privat (vizibil doar n aceasta clas) ce este afiat n exterior prin dou proprieti
publice ( public string BirthDateString, public DateTime BirthDate) ;
private const string dateTimeFormat = @"dd-MMM-yyyy"; este un string folosit pentru
formatarea datelor calendaristice n momentul afirii.
Observaie: pentru stocarea unei date calendaristice s-a folosit structura DateTime definit n biblioteca
"System". VS pune la dispoziie un help util ce se afieaz sub forma unui ToolTip n momentul cnd
ntrziem cu mouse-ul deasupra unui cuvnt cheie. Pentru DateTime helpul tipul acelui cmp si un mic text
descriptiv:

Struct n C# are aceeai semnificaie ca i C clasic: o structur organizat de cmpuri si funcii. Foarte
asemntoare cu o clas, dar nu necesit instaniere pentru a fi utilizat.

Version no.: 2

Page 13 of 83

Proprietile clasei permit modificarea numelei, prenumelui i a datei de natere pentru acea persoan.
Data de natere poate fi modificat prin dou proprietai, una primind ca parametru o structura DateTime ce
nlocuiete direct valoarea variabilei interne, a doua primete un string pe care-l convertete la structura
DateTime.
Observaie: clasa "string" este o clasa nativa in C#, se utilizeaz pentru memorarea irurilor de caractere.
Este folosita in clasa Person pentru salvarea numelui si prenumelui.
Clasa Person are o singur metod (funcie) prin care se obine un string format din cele dou entiti ale
numelui concatenate.

2.3.3 Instantierea Claselor


Clasa Person reprezint doar un ablon dup care se creeaz obiecte (instane) de tip Person. Pentru a
crea obiectul, trebuie folosit comanda new:
Person person1 = new Person();
Prin instruciunea de mai sus s-a creat un obiect numit person1 de tip Person. Comanda new aloc
spaiu de memorie pentru obiect i-l depune la acea locaie.
Se poate declara un obiect si fr crearea unei instane n memorie, dar pan nu se aloc spaiu de
memorie efectiv prin comanda new, acel obiect nu poate fi utilizat.
Person pers1;
pers1 = new Person();
Dac se ncearc apelul unei metode din obiectul declarat , dar neinstaniat,
Person pers2;
pers2.Nume = "vasile...";
System.Console.WriteLine(pers2.GetNameSurname());
C-ul d eroare la compilare: Use of unassigned local variable 'pers2' .
In clasa Program se creeaz o instan (obiect) din clasa Person, se seteaz valorile pentru proprietile
acesteia, apoi se afieaz la consol aceste informaii.
Chiar dac acest program nu utilizeaz mai deloc conceptele POO, este un nceput pentru urmtoarele
dezvoltri n arhitectura POO.

2.3.4 Constructori. Overloading


Constructorul este o funcie special care are acelai nume ca i clasa de definiie i care este obligatorie n
definiia clasei. Chiar dac programatorul nu scrie nici un constructor pentru clasa respectiv, automat VSul insereaz un constructor null n clas:
public Person(){}
Constructorul este prima funcie ce se apeleaz automat dup instanierea obiectului (deja toi membrii
obiectului sunt alocai n memorie) i se folosete pentru diverse setri iniiale sau pentru preluarea
informaiilor furnizate de apelant la crearea obiectului prin comanda new.
De exemplu, utilizatorul dorete sa furnizeze direct numele persoanei in momentul crerii obiectului printrun apel de forma:
Person pers2 = new Person("Dosoftei", "Andrei");
Pentru ca acest construcie s mearg, trebuie creat un constructor care s preia cei doi parametri (nume
i prenume) i s-i salveze n variabilele obiectului.
public Person(string name, string surname)

Version no.: 2

Page 14 of 83

{
}

Name = name;
Surname = surname;

Atentie: daca se introduce un constructor cu un numar de parametri diferit de zero, trebuie sa se scrie si
constructorul implicit (cel cu zero parametri: public Person(){ } ). In caz contrar apare eroarea: No overload
for method 'Person' takes '0' arguments
La fel de bine, utilizatorul ar vrea s furnizeze pe lng numele persoanei, i data naterii n momentul
crerii obiectului:
Person pers2 = new Person("Ionut","Popescu","02-Nov-1990");
DisplayPersonDetails(pers2);
Pentru aceasta, trebuie creat un nou constructor care s primeasc 3 parametri:
public Person(string name, string surname, string birthDate)
{
Name = name;
Surname = surname;
BirthDateString = birthDate;
}
De observat c dei cei doi constructori au acelai nume (nici nu au cum sa fie diferite deoarece
constructorul motenete numele clasei), la instanierea obiectului nu apare nici o eroare, cu toate c n
acel moment se apeleaz constructorul clasei. Care este constructorul apelat? Simplu, se apeleaz
constructorul care se potrivete cu numrul de parametri introdui de apelant. Eroarea apare dac se
creeaz un obiect cu un numar de parametri ce nu se ntlnete la nici un constructor.
Refolosirea aceluiai nume pentru mai multe funcii se numeste suprancrcare (overloading). Dou
funcii pot avea acelai nume, dar trebuie sa se diferenieze prin numrul de parametri sau, la numr egal
de parametri, sa difere tipul acestora.
Observaie: nu se poate folosi acelai nume pentru dou funcii care difer numai prin valoarea returnat.
Evident, constructorul nici nu are valoare returnat, pentru ca el nu este apelat de catre o alta funcie, el
este apelat automat de sistem n momentul crerii obiectului.
Observatie: chiar daca constructorul este prima functie apelata din cadrul obiectului, n cadrul
constructorului se poate face referire la alte functii din obiect. De exemplu, n cel de-al doilea constructor sa utilizat apelul: BirthDateString = birthDate. Acest apel demonstreaz c obiectul este deja
format n momentul apelului constructorului.
Suprancrcarea se utilizeaz i la metodele obinuite ale clasei, nu numai pentru constructori.

2.3.5 Domeniul de vizibilitate pentru componentele unei


clase
Fiecare component a unei clase are definit un domeniu de vizibilitate n funcie de care, acea component
poate fi accesat sau nu din alte clase.
In continuare sunt date principalele domenii de vizibilitate ce pot fi definite in C#:
Public: o component public poate fi accesat att din interior, ct i din exterior, este vizibil n
toate situaiile:

Version no.: 2

Page 15 of 83

Private: este o component ascuns, poate fi utilizat doar n cadrul clasei, nici mcar clasa copil
ce moteneste clasa de baz nu poate utiliza variabila privat. Prin clasa copil ntelegem o alt
clas creat prin derivare din clasa de baz i care moteneste toate componentele clasei parinte,
bineneles excluznd componentele private.

Protected: vizibil n clasa copil, dar nu este vizibil in exteriorul clasei.

Internal: vizibil n aplicaia curent (DDL-ul curent), dar nu este accesibil din alte aplicaii.

Protected Internal: reprezint intersecia ntre cele dou domenii de vizibilitate, componenta este
vizibil doar n clasele derivate i n acelai DDL.

Version no.: 2

Page 16 of 83

2.3.6 Domenii de vizibilitate pentru o clas


Dac clasele sunt create n interiorul altor clase, atunci pot avea toate domeniile de vizibilitate definite mai
sus.
Dac clasele sunt definite direct ntr-un "namespace", atunci ele pot avea atributele internal sau public.
Implicit o clas are atributul internal, deci vizibil doar n proiectul din care face parte.
Namespace-ul reprezint un spaiu de clase i alte componente n interiorul cruia toate aceste
componente sunt accesibile reciproc. In afara acestui spaiu componentele nu sunt vizibile dect dac acel
namespace este adaugat la referinele proiectului i inclus n seciunea "using" (similar cu seciunea
"include" din C clasic).

Version no.: 2

Page 17 of 83

2.4 Conceptele Programrii Orientate Obiect


Sunt patru concepte de baz pe care se construiete POO :
Abstractizare
Incapsulare
Motenire
Polimorfism

2.4.1 Abstractizare
Abstractizarea reprezint posibilitatea ca un program s ignore unele aspecte ale informaiei pe care o
manipuleaz, adic posibilitatea de a se concentra asupra esenialului. Fiecare obiect n sistem are rolul
unui actor abstract, care poate executa aciuni, i poate modifica i comunica starea i poate comunica
cu alte obiecte din sistem fr a dezvlui cum au fost implementate acele faciliti.
POO implementeaz abstractizarea prin intermediul claselor. Clasele definesc proprieti i metode pentru
un obiect de un anumit tip. De exemplu, puteam crea abstractizarea unui cel prin definirea proprietilor
(culoare, nalime, greutate) i a aciunilor (alearg, muc).
Clasele reprezint tipare pentru obiectele reale, iar obiectele reprezint instane ale clasei. Clasa este
unic, n timp ce se pot crea mai multe obiecte din aceeai clas, fiecare obiect avnd o durat de via
determinat de contextul n care a fost creat.

2.4.1.1 Referina obiectelor


Dei programatorul are acces la membrii unui obiect prin intermediul numelui obiectului, nu trebuie
confundat denumirea cu obiectul n sine. Denumirea reprezint doar o referin ctre zona de memorie
unde s-a creat obiectul respectiv. Obiectele sunt plasate ntr-o stiv (heap) de obiecte n momentul crerii
lor i sunt eliminate cnd obiectele sunt distruse. De regul, un obiect are o singur referin, dar sunt
situaii cnd pot exista mai multe referine la acelai obiect. Aceste cazuri apar cnd se realizeaz atribuiri
ntre obiecte. De fapt, atribuirile nu se realizeaz ntre obiecte, ci ntre referintele ctre obiecte.
Putem exemplifica prin cteva linii de cod n clasa Program:
#region Atribuire de referinte
Person persReference1, persReference2;
persReference1 = new Person("Marcel","Chirica");
persReference2 = new Person("Viorel", "Butnaru");
Console.WriteLine(" Persoana persReference1 se numeste: {0} ",
persReference1.GetNameSurname());
Console.WriteLine(" Persoana persReference2 se numeste: {0} ",
persReference2.GetNameSurname());
//atribuire de referinte
persReference1 = persReference2;
Console.WriteLine(" Dupa atribuire, Persoana persReference1 se
numeste: {0} ", persReference1.GetNameSurname());
Console.WriteLine(" Dupa atribuire, Persoana persReference2 se
numeste: {0} ", persReference2.GetNameSurname());
#endregion
Rezultatul rulrii acestui cod este urmtorul:

Version no.: 2

Page 18 of 83

Observaie: dup atribuirea persReference1 = persReference2 , obiectul persReference1 este pierdut


definitiv deoarece nu mai exist nici o referin la el.
De reinut c referina nu reprezint obiectul n sine, ci doar adresa acestuia, este similar pointerului definit
n C-ul clasic.

2.4.2 Incapsulare

2.4.2.1 Conceptul de ncapsulare


Incapsularea este numit i ascunderea de informaii n sensul ca asigur faptul c obiectele nu pot
schimba starea intern a altor obiecte n mod direct (ci doar prin metode puse la dispoziie de obiectul
respectiv); doar metodele proprii ale obiectului pot accesa starea acestuia.
Fiecare tip de obiect expune o interfa pentru celelalte obiecte care specific modul cum acele obiecte pot
interaciona cu el. In spatele interfeei obiectul poate fi privit ca o cutie neagr (black box) ce realizeaz
taskurile afiate prin interfa, dar ascunde detaliile acestor implementri.
Sunt trei componente ale unui obiect ce implementeaz conceptul de ncapsulare:

Interfaa obiectului: interfaa reprezint un set de proprieti, metode, variabile i evenimente


declarate publice n interiorul obiectului. Orice obiect din afar are acces doar la aceste cmpuri
declarate n interfa.
Interfaa arat ca o clas, dar fr codul efectiv din spatele ei. Chiar dac nu au cod, ele sunt importante
pentru c definesc contractul pe care clasa respectiv trebuie s-l respecte. Sunt foarte utile atunci cnd se
ncepe construcia unui proiect mai mare i n faza de nceput se definesc aceste interfee ntre obiecte.

Implementarea sau comportamentul obiectului: reprezint codul efectiv ce realizeaz taskurile din
interfa. Acest cod include i alte cmpuri i funcii private, invizibile n exterior, dar apelate n
interior pentru efectuarea anumitor sarcini.
Observaie: programatorul poate schimba oricnd codul unui obiect att timp ct interfaa rmne
neschimbat; Obiectul va fi folosit n continuare n acelai mod, indiferent de modul lui de implementare.

Membrii sau variabilele obiectului: definesc starea obiectului. Obiectele ce aparin de aceeai clas
sunt identice cu excepia valorilor stocate n variabilele interne. Dou obiecte de tip Person au
aceeai structur, aceeai interfa, n schimb au nume si date de natere diferite.
Observaie: de reinut c proprietatea nu stocheaz date, ci doar este un mijloc de a accesa datele stocate
ntr-o variabil intern.

2.4.2.2 Interfaa clasei Person


S modificm programul nostru prin adugarea unei interfee la clasa Person. Ca regul de programare,
numele interfeei este data de numele clasei, la care se pune prefixul "I".
Se face click dreapta pe proiectul din VS i se alege opiunea Add Item/Interface. Numel interfeei va fi
IPerson:

Version no.: 2

Page 19 of 83

Revenim la clasa Person i specificm faptul c aceast clas implementeaz interfaa IPerson, punnd
dou puncte dup definiia clasei urmate de numele interfeei implementate::
public class Person : IPerson
Dup aceast modificare, VS-ul va verifica ca toate componentele definite in interfa vor fi implementate n
clas. Deci interfaa reprezint contractul, iar clasa implementarea contractului. Avantajul interfetei este c
pot s-o utilizez ca un substitut pentru clasa Person n dialogul cu celelalte clase ale programului. De
exemplu, funcia de afiare nu mai primete ca parametru clasa Person, ci interfaa IPerson:

De ce este un avantaj? Pentru c dup ce am creat interfeele, fiecare mebru din echipa de programare
poate trece la implementarea codului, utiliznd interfaa unui alt obiect fr ca acel obiect sa fie efectiv
implementat. Se poate lucra n paralel prin implementarea simultan a obiectelor.
Un alt avantaj este dat c programatorul nu este lsat s uite implementarea unei anumite funcii. Dac
clasa nu include toate componentele interfeei, atunci VS d eroare. De exemplu, s adugm n interfa o
nou proprietate ce returneaz vrsta persoanei:
uint GetPersonAge { get; }
Dac se ncearc execuia programului n acest caz, obinem urmtoarea eroare:

Se adaug proprietatea n clasa Person i eroarea dispare:

S-a utilizat cmpul year din structura DateTime i prin diferena lor s-a aflat numrul de ani ntre ziua de azi
i data naterii. Este posibil ca persoana respectiv s nu mplinit nc anii (de exemplu, suntem n iunie i
ea face anii n noiembrie). In acest caz facem corecia scznd o unitate din numrul anilor.
Vrsta persoanei se poate afia prin modificarea funciei DisplayPersonDetails(IPerson pers):
Console.WriteLine("\n\t\t BirthDate = {0} Age = {1}", pers.BirthDateString,
pers.GetPersonAge);

Version no.: 2

Page 20 of 83

Observaie: proprietatea GetPersonAge este de tip "read only" adic lucreaz doar ntr-un singur sens
(lipsete componenta "set" din definiie). Nu se poate seta vrsta persoanei, ea se calculeaz ntotdeauna
n funcie de ziua curent.

2.4.3 Motenirea

2.4.3.1 Conceptul de motenire


Motenirea permite definirea i crearea unor clase specializate plecnd de la clase (generale) deja definite.
Noile clase pot mprti (i extinde) comportamentul lor, fr a fi nevoie de a-l redefini. Aceasta se face de
obicei prin gruparea obiectelor n clase i prin definirea de clase ca extinderi ale unor clase existente.
Conceptul de motenire permite construirea unor clase noi, care pstreaz caracteristicile i comportarea,
deci datele i funciile membru, de la una sau mai multe clase definite anterior, numite clase de baz, fiind
posibil redefinirea sau adugarea unor date i funcii noi. O clas motenitoare a uneia sau mai multor
clase de baz se numete clas derivat (clas copil). Esena motenirii const n posibilitatea refolosirii
lucrurilor care funcioneaz.
Motenirea reprezint punctul forte al programrii pe obiecte deoarece permite ntr-un mod foarte simplu i
performant reutilizarea codului. S presupunem c trebuie creat o nou clas Student prin care s
gestionm situaia colar a studenilor. Evident, studentul este o persoan, deci toate atributele i
metodele definite pentru o persoan, sunt valabile i pentru student.
In plus, clasa student mai trebuie s memoreze anul de studiu, media scolar pe acel an de studiu, dac
este student cu tax sau fara tax, numrul de credite obtinue, etc. Deci, din punct de vedere conceptual,
clasa student este o extindere a clasei Person.
Mai ntai se creeaz interfaa IStudent ce extinde interfaa IPerson:

Mostenirea unei clase se face prin constructia : .

Instruciunea "class Student:Person, IStudent" definete o nou clas Student care motenete
clasa Person i interfaa "IStudent". Aceasta nseamn c, clasa student beneficiaz de toate metodele i
membrii non-privai din clasa printe i trebuie s implementeze metodele i proprietile delcarate
suplimentar n interfaa "IStudent".
Instanierea unei clase copil se face prin acelai mecanism ca la o clas independent:

Version no.: 2

Page 21 of 83

Student stud1 = new Student("Alina","Ciubotaru","07-Nov-1985");


DisplayPersonDetails(stud1);

Observaie: funcia " private static void DisplayPersonDetails(IPerson pers)" din clasa
"Program" primete ca parametru o instan a interfeei "IPerson" (de fapt o instan a unei clase derivat
din IPerson, interfaa nu poate fi instaniat). Totui, aceast functe s-a apelat cu o instan a clasei
Student (DisplayPersonDetails(stud1);) i programul a rulat fr erori.
Concluzie: n locul referinei la clasa de baz se poate utiliza referina clasei derivate, deoarece clasa
derivat conine toate cmpurile clasei de baz. Evident, reciproca nu este adevrat. Dac ncercm s
apelm funcia cu o instana a clasei Person n timp ce ea ateapt o referin la clasa Student, se obine
eroare de compilare:

Constructorii clasei de baz trebuie rescrii deoarece clasa Student are mai muli membri care trebuie
initializai. In schimb, constructorul clasei copil apeleaz constructorul clasei printe:
Explicit, cnd se specific care constructor din clasa parinte se apeleaz
(:base(name,surname,birthDate))
public
Student(string
name,
string
surname,
string
birthDate) :base(name,surname,birthDate)

Implicit, cnd se apeleaz constructorul implicit al clasei printe:


public Student(string name, string surname)
{
Name = name;
Surname = surname;
Burse = BurseType.FaraBursa;
Address = string.Empty;
Class = "0000";
}

Intotdeauna la instanierea unei clase copil se apeleaz mai nti constructorul clasei printe. Acest lucru se
poate demonstra uor dac punem cte un mesaj n fiecare constructor i urmrim ordinea de afiare a
acestor mesaje:

Fereastra consol afieaz cele dou mesaje din constructori n ordinea printe-copil:

2.4.3.2 Suprascriere (override)

Version no.: 2

Page 22 of 83

In clasa copil se pot accesa toate metodele, cmpurile i proprietile non-private din clasa de baz. De
exemplu, constructorul clasei Student seteaz proprietatea "Name" ca i cum aceasta ar fi o proprietate
intern clasei. "Name" nu a fost definit n Student, dar este definit n clasa printe "Person", deci este
accesibil n clasa copil.
Totui, exist necesitatea ca anumite metode s fie suprascrise n clasa copil. S spunem c n clasa de
baz Person avem o funcie "GetPersonQuality" prin care a vrea s afiez numele persoanei i calitatea
pe care o detine n instituie (student, profesor, administrator, etc). Clasa de baz "Person" nu are nici o
calitate, deci funcia "GetPersonQuality" pentru aceasta clas va aduce numai numele persoanei:

In clasa Student, respectiva funcie se suprascrie, astfel inct s afieze calitatea studentului:

Prin rularea programului, clasa Program va apela funcia GetPersonQuality specifica instanei primite:

In Consol putem observa rezultatele; pentru Ionu, care este persoan funcia afieaz doar numele, iar
pentru Alina afieaz i grupa din care face parte (n cazul de fa grupa 0000).

Nu orice funcie din clasa de baz poate fi suprascris n clasa copil, ci doar dac este declarat cu
atributul "virtual". In clasa copil metoda se suprascrie prin folosirea atributului "override".

2.4.3.3 Identificatorii this i "base"


"This" este o metod specific tuturor obiectelor i care returneaz o referin la acel obiect. Aa cum din
afara clasei accesm componentele interne prin numele obiectului (pers.GetPersonQuality()), n
interiorul acestuia le accesm cu identificatorul this (this.Surname = surname). Bineneles, utilizarea
lui this este oarecum superflu, putem avea acces foarte bine la componentele interne i fr this.

2.4.3.3.1
"This" separ componentele interne de parametrii cu acelai
nume
Totui este util aceast referin cnd exist ntr-o funcie dintr-o clasa variabile locale sau parametri care
au acelai nume cu al componentelor din clas (cu toate ca acest lucru nu e bine s se ntmple). In acest
caz se utilizeaz this pentru a accesa componentele clasei n contrast cu variabilele locale.

Version no.: 2

Page 23 of 83

De exemplu, avem o clas ce conine variabilele private "Name" si "Surname" i o funcie care primete
aceste valori prin parametri i seteaz variabilele locale cu valorile primite:

Instruciunea "this.Name = Name" atribuie variabilei interne din clasa numit "Name" valoarea pe care o
primete prin parametrul "Name". Cele dou variabile au acelai nume, de aceea folosim "this" pentru
identificare.

2.4.3.3.2

"This" trimite referina obiectului curent

De asemenea, "this" este utilizat pentru a transmite referina obiectului curent la funciile ce primesc ca
parametru un astfel de obiect. De exemplu, a dori s apelez funcia de afiare la Consol
"DisplayPersonDetails" direct din constructorul clasei "Person". Funcia primete ca parametru o
referin la clasa Person, referin pe care eu o trimit din interiorul acestui obiect prin identificatorul "this".
Facem public funcia "DisplayPersonDetails" ca s-o pot accesa din afar i apelm funcia din
constructorul clasei "Person":

Observm diferena: din clasa "Program" funcia se apeleaz cu referina la clasa Person
(DisplayPersonDetails(pers2)),
iar
din
clasa
"Person"
se
apeleaz
cu
"this":
Program.DisplayPersonDetails(this).

2.4.3.3.3

"This" identific funcia suprascris n clasa derivat

Observm c funcia "GetPersonQuality" are implementri diferite n clasa printe i clasa copil. Putem
apela fiecare funcie separat dac specificm obiectul din care face parte funcia prin identificatorul "this"
sau "base".
De exemplu, doresc ca funcia "GetPersonQuality" s afieze calitatea obiectului printe la care adaug
noua calitate obinut de clasa copil:

Sunt n funcia "GetPersonQuality" din clasa Student i apelez funcia "GetPersonQuality" din clasa
printe pentru a obine calitatea clasei "Person". Accesarea funciei din clasa de baz se face cu
identificatorul "base".
Dac a nlocui "base" cu "this" a obine un apel recurent la infinit ce d stiva peste cap:

Version no.: 2

Page 24 of 83

In constructorul clasei "Student" pot folosi identificatorii "this"i "base" pentru membrii clasei fr s am erori
de compilare. "Name"-ul l setez folosind clasa de baz, "Surname" folosind obiectul derivat.

Rezultatul este acelai, deoarece acel membru (Name, Surname) are o singur locaie n memorie i
indiferent cum este accesat, prin pointerul clasei de baz sau pointerul clasei copil, se ajunge n aceeai
locaie de memorie.

2.4.3.3.4

Ascunderea funciilor din clasa de baz

Chiar dac funcia nu e declarat "virtual" n clasa de baz, ea poate fi suprascris n clasa derivat: pur i
simplu se implementeaz aceeai funcie cu un alt cod. Utilizatorii clasei derivate nu vor vedea deloc funcia
din clas de baz, ei vor avea acces doar la implementarea din clasa derivat. Dar n interiorul clasei
derivate, putem accesa funcia din clasa printe folosind identificatorul "base".

2.4.3.4 Metode i variabile statice


Am observat c se poate declara un obiect i fr crearea unei instane n memorie (de exemplu Person
pers;), dar pn nu se aloc spaiu de memorie pentru acel obiect efectiv prin comanda new, obiectul nu
poate fi utilizat.

Dac se incearc apelul unei metode din obiectul declarat , dar neinstaniat:

C-ul d eroare la compilare: Use of unassigned local variable 'pers' .

Version no.: 2

Page 25 of 83

2.4.3.4.1

Metode statice

Si totui, se pot accesa metode sau variabile , chiar dac nu a fost creat obiectul. Aceste variabile trebuie
declarate static i ele sunt create ntr-o zon special de memorie la declaratia clasei. Am vzut cn
clasa "Program" ambele funcii (Main , DisplayPersonDetails) au fost declarate static. Nimeni nu a
creat vreo instan pentru clasa "Program" i totui funciile au fost apelate i rulate.
O funcie se declar static atunci cnd nu este legat de o instan anume a unui obiect, este o funcie de
uz general i d acelai rezultat indiferent de obiectul din care s-ar apela. De exemplu, putem declara n
clasa Person o metod ce returneaz data curent. Funcia nu are nici o legtur cu o persoan anume,
ea pur i simplu returneaz data calendaristic, indiferent de numele persoanelor instaniate, de aceea
declarm aceast funcie de tip "static".

In clasa "Program" apelm direct funcia folosind numele clasei i nu o instan de obiect:
Console.WriteLine("Today is " + Person.GetCurrentDate());.
Observatie: nu se pot apela funcii statice folosind referina obiectelor:

2.4.3.4.2

Variabile statice

Variabilele statice au acelai statut ca i metodele statice descrise mai sus. De exemplu, se declar o
variabil currentDate n clasa Person de tip static:
private static string currentDate = string.Empty;
i apoi funcile cu care s accesm aceast variabil prin intermediul instanei unui obiect:

Modificm pe rnd valoarea variabilei prin dou obiecte separate ale clasei Person i afim de fiecare dat
currentDate-ul:

Version no.: 2

Page 26 of 83

Rezultatul este dat mai jos:

Se poate observa c, dup ce pers2 a schimbat valoarea la currentDate, acea valoare s-a transferat i la
person1, chiar dac person1 este obiect separat.
Concluzie: varabilele statice au doar o singur instan n memorie, iar dac se modific valoarea prin
intermediul unui obiect, aceast modificare apare la toate obiectele.
Observaie: mai jos sunt date cteva aspecte particulare ale funciilor statice:
O funcie static nu poate avea unul din urmtoarele atribute: override, abstract, virtual
Nu se pot apela funciile statice din clasa printe folosind identificatorul base. Trebuie folosit numele
clasei ca identificator.
Intr-o clas static putem accesa doar membrii statici ai clasei

2.4.3.5 Clase abstracte


O clas declarat abstract este un tip special de clas. Pe lng componentele obinuite oricrei clase,
aceasta conine componente declarate abstracte. Membrii abstraci sunt metode sau proprieti ce nu au
definit implementarea n clas, doar amprenta funciei (exact ca intr-o interfa). Ca i interfaa, aceste
clase nu pot fi instaniate, ci doar motenite, iar clasa derivat trebuie sa implementeze toi membrii
abstraci ai clasei de baz.
Cea mai faimoas clas abstract este clasa "Object" (sau "object", este acelai lucru). Reprezint clasa de
baz pentru toate clasele din C#, implicit, orice clas deriva din clasa Object, dac nu se specific alt
clas de baz.

2.4.3.5.1

Diferene ntre clasele abstracte i interfee

Interfeele sunt similare cu clasel abstracte, dar cu unele diferene:


O clas abstract poate conine i metode sau proprieti ce nu sunt abstracte, au codul
implementat, interfaa conine doar membri abstraci.
In C# o clas poate s moteneasc doar o singur clas de baz abstract, dar mai multe
interfee
O interfa nu poate conine constante, cmpuri, constructori, operatori, etc, ea reprezint doar un
contract abstract pe care clasele derivate trebuie s-l implementeze.
Interfeele nu pot avea membri statici, sau atribute de tipul abstract, public, protected, internal,
private, virtual, override deoarece nu au sens n acest context.

2.4.4 Polimorfismul

Version no.: 2

Page 27 of 83

Polimorfismul este abilitatea de a procesa obiectele n mod diferit, n funcie de tipul sau de clasa lor. Mai
exact, este abilitatea de a redefini metode pentru clasele derivate. De exemplu, pentru o clas Figura
putem defini o metod arie. Dac Cerc, Dreptunghi, etc. vor extinde clasa Figura, acestea pot redefini
metoda arie.
Analiznd exemplul nostru, avem polimorfism n cazul funciei "GetPersonQuality()". In clasa de baz
"Person" aceasta are o implementare, iar n clasa derivat aceeai funcie are un alt cod. Ambele funcii
sunt apelate n clasa Program de metoda "public static void DisplayPersonDetails(Person
pers)". Observm ca metoda primete ca parametru clasa e baz, dar n momentul apelului, referina
"pers" primit poate fi foarte bine o referin la clasa "Student". In primul caz se apeleaz metoda din clasa
de baz cu un anume efect, n al doilea caz, se apeleaz metoda din clasa Student cu un alt efect.
Din clasa Person am mai putea deriva o alta clasa "Profesor" ce implementeaz n mod diferit funcia
"GetPersonQuality()". Referina la clasa "Profesor" trimis metodei "DisplayPersonDetails
(Person pers)" ar avea alt efect dect primele dou. Deci prin polimorfism nelegem c acelai obiect
se poate comporta diferit n funcie de contextul n care este folosit (dac se utilizeaz clasa de baz sau o
anumit clas derivat).

Version no.: 2

Page 28 of 83

2.5 Aspecte ale POO n mediul de dezvoltare Microsoft Visual Studio


Programarea Orientat Obiect este un concept ce a fost implementat de mai multe limbaje de programare:
C++, Java, Pascal, C#, etc. Toate aceste limbaje suport conceptele definite de POO, dar fiecare are
anumite particulariti ce nu in de standardul POO.
In acest capitol sunt date cteva particulariti ale dezvoltrii programelor POO n mediul Visual Studio.

2.5.1 Garbage collection

2.5.1.1 Eliberarea memoriei n mod automat


Garbage Collection reprezint o soluie la o problem veche n lumea programatorilor POO: curarea
memoriei de obiectele ce nu mai sunt folosite. Atunci cnd se creez un nou obiect prin comanda "new",
acesta va fi stocat n memorie i apoi utilizat. Dup utilizare trebuie dat comanda de distrugere a obiectului
pentru a elibera memoria. In caz c se uit acest aspect, atunci se constat c pe parcursul rulrii
programului, acesta crete n dimensiune pn ocup toat memoria disponibil. Este uor s uii despre
distrugerea unui obiect, mai ales cnd referina acestuia este dat ca parametru n tot felul de funcii i se
pierde urma acestuia. De aceea, n VS ruleaz programul Garbage Collection (GC).
GC este un program ce ruleaz n background, ce are ca scop eliminarea din memorie a obiectelor care nu
mai sunt folosite. Programul elibereaz memoria de obiecte inutile, rearanjeaz obiectele valide n memorie
i elibereaz astfel resursele sistemului.
Procesul GC se declaneaz periodic n mod automat dar poate fi startat i de ctre utilizator. In principiu,
el se declaneaz automat cnd apare una din situaiile:
un obiect rmne fr referin
stiva de obiecte a ajuns la saturaie
In momentul distrugerii unui obiect, GC-ul apeleaz destructorul obiectului respectiv. Dac aceast metod
nu a fost suprascris, atunci obiectul este distrus n mod direct. Destructorul implicit elibereaz doar
memoria gestionat de C#, el nu poate elibera resursele externe alocate explicit de ctre programator:
fiiere, conexiuni la baze de date, etc. In acest caz, sunt necesare anumite operaii nainte de distrugerea
obiectului (nchiderea conexiunii la baza de date, eliminarea altor obiecte conexe, etc), i programatorul
trebuie s suprascrie destructorul clasei i execut aceste taskuri.
Nu se stie niciodat precis cnd se declaneaz procesul de curire a stivei de ctre GC, ns se poate
fora pornirea acestei operaii prin apelarea funciei "GC.Collect()".
Exemplificm aceste concepte prin adugarea destructorului n clasa "Person":

In clasa "Program" realizm o funie (CreateDestroyPerson())ce creeaz un obiect de tip Person, apoi
la ieirea din funcie se apeleaz GC.Collect:

Version no.: 2

Page 29 of 83

Rezultatul acestei operaii se vede la concol:

Se observ c, GC.Collect distruge obiectele ce nu mai sunt necesare n acel moment, i anume, obiectul
creat n funcia "CreateDestroyPerson()". Acel obiect este intern funciei, deci la ieirea din aceast
funcie, toat memoria alocat n interiorul ei trebuie eliberat, deci apt pentru Garbage Collection.

2.5.1.2 Eliberarea memoriei la cerere


Atunci cnd un obiect creeaz alte obiecte ce nu pot fi procesate de GC (conexiuni la baza de date,
deschiderea de fisiere), este bine ca distrugerea unui astfel de obiect s se fac n mod controlat, de ctre
programator.
In acest scop programatorul are la dispoziie o interfa "IDisposable" ce conine o singur funcie:
"Dispose()". O clas ce moteneste aceast interfaa trebuie s implementeze funcia respectiv.
Aceast funcie se apeleaz explicit de ctre programator atunci cand obiectul nu mai este necesar, sau
implicit cnd se creeaz obiectul ntr-o seciune de tip "using".
Modificm clasa Person astfel nct s implementeze funcia Dispose:

Iar n clasa Program crem o persoan prin clauz "using":

Cnd se termin blocul "using" se apeleaz automat funcia "Dispose" a obiectului creat pentru eliberarea
resurselor alocate n acel obiect. Analizm mesajele afiate la consol i observm c obiectul "Ionut
Popescu" s-a distrus imediat dup nchiderea blocului "using":

Version no.: 2

Page 30 of 83

2.5.2 Excepii i tratarea excepiilor


Sunt situaii cnd parcurgerea normal a programului se ntrerupe din cauza unor erori neprevzute
(mprire la zero, conexiunea cu baza de date nu mai funcioneaz, scrierea n fiier blocat deoarece
acesta nu exist sau este ReadOnly), i n acel moment apare pe ecran un mesaj de eroare dup care
execuia programului se suspend.
De exemplu, s lum cazul unei mpriri la zero: se adaug n clasa "Program" o funcie ce returneaz
rezultatul mpririi a dou numere:

Rezultatul apelului este dat in continuare:

Se observ c primul apel 3/2 a returnat rezultatul corect (bine, dac nu inem cont de zecimale), cel de-al
doilea: 3/0 a produs eroare care a blocat programul.
Evident c funcia este scris greit, ar trebui c orice mprire la zero s fie exclus printr-un if simplu, dar
nu n toate cazurile se pot scrie variante de "if " care s exclud toate condiiile de eroare. De aceea, VS-ul
pune la dispoziia programatorilor un sistem simplu i performant de tratare a excepiilor, astfel nct,
acestea s nu duc la blocarea programului. Acest mecanism de prindere a excepiilor este format din
structura trycatchfinally:

Version no.: 2

Page 31 of 83

In seciunea try se introduce codul pasibil de erori iar seciunea catch este blocul ce trateaz aceste
erori. In aceast seciune se intr doar dac a aprut o excepie. In cazurile n care sunt anumite aciuni ce
trebuie executate (nchidere de fiiere, conexiuni, etc), indiferent dac s-a produs sau nu o excepie,
programatorul poate insera n seciunea finally codul pentru nchiderea acestor resurse. Sectiunea finally
se executa ntotdeauna, direct dupa seciunea try dac nu au fost erori, sau dup catch dac s-a produs
o eroare. Programul ruleaz seciunea try, iar dac o instruciune din aceasta seciune produce eroare,
imediat dup acea instruciune se sare la seciunea catch. Instruciunile din seciunea try ce urmeaz
dup instruciunea de eroare nu se mai execut, de aceea este necesar capitolul finally care sa faca
curaenie, indiferent dac s-a produs sau nu eroare.
In exemplul urmtor se arat necesitatea includerii seciunii finally n structura "try". Instruciunea
"myFile.Close();" trebuie executat n mod obligatoriu, indiferent ce eroare se ntmpl pe parcurs, n
caz contrar, acest fiier va rmne blocat n Windows i nu mai poate fi accesat de alte programe.

In seciunea catch este accesibil obiectul Exception ce include informaii referitoare la cauza erorii (n
cazul de fa am utilizat membrul "Message" pentru a afia la consol textul erorii.

Version no.: 2

Page 32 of 83

3 Dezvoltarea aplicaiilor de tip GUI in VS.NET


3.1 Etapele dezvoltrii unei aplicaii Windows n VS.NET
Pn acum am utilizat proiecte de tip "Console" pentru exemplificarea conceptelor programrii pe obiect.
Sunt cele mai simple proiecte, se aseamn cu aplicaiile dezvoltate n limbajele clasice, dar nu au deloc o
interfa grafic performant. Nu se regsesc imagini, butoane sau alte controale grafice cu care suntem
obinuii ntr-o aplicaie de tip "Windows".
De aceea, VS.NET pune la dispoziie i alte tipuri de proiecte, unde programatorul dispune de un spectru
foarte larg de clase, sub forma unor controale vizuale, cu ajutorul crora poate s construiasc ntr-un timp
redus aplicaii cu interfee grafice performante. Aceste controale includ funcionalitatea necesar pentru
marea majoritate a programelor, de aceea ele au devenit un fel de standard n domeniul programrii
vizuale.
Programarea VS.NET nu este o programare efectiv vizual n conceptul dezvoltat de National Instruments
prin tehnologia LabView, n care programatorul nu introduce linii de cod, ci dezvolt programul doar prin
operaii drag&drop. Totui, programarea n VS.NET se apropie foarte mult de acest concept, cea mai mare
parte a codului unui program fiind inclus automat de VS.NET prin inserarea drag&drop a controalelor
vizuale, programatorul trebuie s se ocupe doar de tratarea evenimentelor specifice acestor controale.
Paii pe care trebuie s-i parcurg un programator pentru dezvoltarea unei aplicaii Windows standard sunt
urmtorii:
se deschide o form de lucru adaptat tipului de aplicaie (Windows application, WEB, DLL, etc);
se poziioneaz cu ajutorul mouse-ului controalele grafice ce realizeaz interfaa ntre aplicaie i
utilizator. Din fereastra Properties a controlului se seteaz starea acestuia (comportamentul su
static);
se scrie cod pentru tratarea evenimentelor specifice fiecrui control n parte (comportament
dinamic);

Version no.: 2

Page 33 of 83

3.2 Prima aplicatie Windows: "Hello world"


Pentru a exemplifica modul de programare n VS.NET se va crea o aplicaie grafic care s afieze pe
ecran mesajul Hello world la apsarea unui buton.
Se deschide un nou proiect (Open/Project/Windows Application) i se seteaz denumirea acestuia: "Hello".

Automat VS-ul creeaz o form numit Form1 n care se vor depune toate controalele vizuale necesare
aplicaiei. Fr a scrie nici o linie de cod, am obinut deja o aplicaie funcional care afiez pe ecran o
fereastr numit Form1 ce rspunde la o mulime de evenimente venite din partea sistemului: mrire,
micorare, nchidere, redimensionare, etc.

De fapt, aplicaia are destule linii de cod ce au fost introduse automat de VS n momentul crerii proiectului:
este inserat o pagin Program.cs (ca i la proiectul de tip Console Application) ce
include codul de startare a programului:

Observaie: "[STAThread]" este un atribut ce seteaz apartamentul threadului curent la tipul single
threaded. Are sens numai dac n program se apeleaz obiecte de tip COM.

Version no.: 2

Page 34 of 83

Implicit se scrie o clasa Program care conine funcia Main ce reprezint punctul de intrare n program.
Folosind funcii statice din clasa Application, functia Main face anumit einiializri valabile n toat aplicaia
i apoi creeaz un obiect din clasa Form1 pe care-l lanseaz n execuie:
Application.Run(new Form1());

Tot VS-ul creeaz automat o clas numit Form1 n care programatorul va insera
controalele care s asigure interfaa ntre program i utilizator. Clasa Form1 nu conine
iniial nici un control, este o fereastra simpl, dar care asigur toat funcionalitatea unei
ferestre de program.

De unde tie clasa noastr Form1 s rspund la diverse aciuni ale mouse-ului din moment ce noi nu am
scris nici o linie de cod ? Simplu, n definiia clasei Form1 se observ c ea motenete clasa Form
(public partial class Form1 : Form) care la rndul ei motenete clasa Panel care motenete
clasa Mobile control i tot aa una din aceste clase superioare include metode care s raspund la
aciunile mouse-ului.
In constructorul clasei Form1 se apeleaz funcia InitializeComponent();. Aceast funcie este
scris automat de VS n funcie de controalele pe care programatorul le insereaz n form prin operaia
drag&drop. Initial, neavnd nici o componenta n form, funcia de iniializare se ocup doar de setrile
formei (seteaz titlul fereastrei, iniializeaz lista "components" unde va stoca controalele formei):

Personalizm forma, prin adaugarea unei etichete (label) n forma i un buton. La click pe buton va aparea
n eticheta textul Hello World.

Version no.: 2

Page 35 of 83

Din fereastra "Tool Box" din stnga (dac nu este vizibil, atunci se deschide din meniul View/Toolbox) se
aduce prin drag&drop dou controale: etichet (label) i buton (button).

Se selecteaz etichet i se acceseaz fereastra de proprieti ale acesteia. Pentru mai


mult efect, se insereaz o imagine n back-ground-ul etichetei, "autosize" = false pentru a
putea modifica dimensiunea, se seteaz mrimea fontulului i culoarea:

Se selecteaz butonul i similar i se ataeaz textul "Say Hello". Se intr n fereastra de


proprieti, pagina de evenimente i se face double click pe evenimentul "Click":

Version no.: 2

Page 36 of 83

In felul acesta se seteaz funcia "button1_Click" care se execut n momentul cnd utilizatorul face
"click" pe buton.
Dup aceste operaiuni, codul din programul nostru va arata astfel:

Funcia InitializeComponent() se modific automat n funcie de controalele adugate de noi i de setrile


iniiale date acestora (culoare, font, dimensiuni, etc).
Singura funcie scris de programator este handler-ul evenimentului button1.Click n care se specific
aciunea ce se execut la acionarea butonului button1:

3.2.1 Funcia InitializeComponent

Version no.: 2

Page 37 of 83

Aceast funcie este scris automat de VS i se apeleaz n constructorul clasei Form1. Se construiete
prin intemediul design-erului, orice modificare pe care noi o facem n design (adaugarea unui control,
schimbarea unor proprieti, etc) se traduce automat prin cod adugat n funcie.
In prima parte a functiei se creeaza un obiect resources de tipul ComponentResourceManager prin
intermediul cruia se va gestiona setul de controale inserate n forma. Apoi se instaniaz pe rnd cte un
obiect pentru fiecare control inserat de noi cu ajutorul mouse-ului n forma de lucru. In cazul de fa sunt
numai 2 controale:

Dup instaniere sunt setate proprietile acestor controale, n funcie de modificrile efectuate de noi n
cadrul design-erului:
..
this.button1.Location = new System.Drawing.Point(93, 189);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);

3.2.2 Interceptarea evenimentelor


In fereastra de design (Form1.cs [design]) am inserat un buton numit button1 dup care am dat doubleclick pe el. Automat se intra in fereastra Form1.cs i se creeaz o funcie:
private void button1_Click(object sender, EventArgs e)
{
}
Acesta este funcia ce se apeleaz automat cnd se execut click pe butonul button1. De unde tim acest
lucru? Ne uitm n funcia InitializeComponents() i vedem ca s-a introdus o linie n plus la capitolul destinat
butonului:
this.button1.Click += new System.EventHandler(this.button1_Click);
Instruciunea de mai sus specific ca s-a adugat un nou handler (o nou funcie) care sa rezolve
evenimentul button1.click lansat automat n sistem la acionarea butonului.
Comentariu:
Programarea n Windows este o programare bazat pe evenimente. Este o concepie diferit fa
de programarea clasic n care se preia controlul microprocesorului la intrarea n funcia main i apoi se
merge din funcie n funcie pn la terminarea programului. In tot acest timp, microprocesorul execut o
anumit funcie sau st ntr-o anumit bucl.
Un program scris n Windows nu urmeaz aceast regul. Se intr n funcia main unde se
instaniaz obiectele de lucru, se afieaz fereastra de interfa cu utilizatorul i apoi se elibereaz
microprocesorul. In momentul n care utilizatorul realizeaz o anumit aciune (apas o tast, acioneaz
mouse-ul, etc), se produce un eveniment n sistem, eveniment care trebuie procesat corespunztor de
programul Windows.
In programul nostru s-a specificat c evenimentul produs de acionarea butonului (this.button1.Click ) va fi
rezolvat de funcia button1_Click . Funcia primete ca parametri obiectul care a produs evenimentul (object
sender), precum i un obiect de tip EventArgs n care putem gsi informaii despre evenimentul respectiv.

Version no.: 2

Page 38 of 83

Ce trebuie s se ntample cnd se face click pe buton? Acest lucru l hotrte programatorul care dezvolt
programul i a pus acel buton n fereastra. In cazul nostru, dorim ca la acionarea butonului s apar un
mesaj n eticheta de deasupra butonului:
label1.Text = @"Hello World";
Aceast instruciune este singura linie de cod scris de noi n tot acest program, de restul se ocup VS-ul.
De fapt sunt mult mai multe evenimente pe care aplicaia noastr le intercepteaz: nchiderea, mrirea,
deplasarea ferestrei, evenimentele mouse-ului, etc. Chiar dac noi nu am scris funcii care sa trateze
aceste evenimente, ele sunt tratate automat de VS.
Sunt mai multe evenimente trimise de sistem ctre buton la care putem rspunde prin ataarea unor funcii
corespunztoare. Setul de evenimente primite de un control sunt vizibile n fereastra de proprieti aferent
acestuia. Fereastra include dou pagini de proprieti selectabile prin butoanele
controlului) i

(proprietatile statice ale

(pagina cu evenimentele asociate controlului).

In figura de mai sus sunt date cele dou pagini de proprietati. In pagina cu evenimente se observ c s-au
adugat dou handler-e la evenimentele MouseEnter (mouse-ul intra n zona butonului), respectiv
button1_MouseEnter
i
MouseLeave
(mouse-ul
prsete
zona
butonului),
respectiv
button1_MouseLeave. Funciile s-au adugat prin double-click n dreptul acestor evenimente din pagina
de proprieti.

Corpul funciilor este format dintr-o singur instruciune care schimb textul afiat de buton n Mouse
enter, respectiv Mouse leave.

Version no.: 2

Page 39 of 83

3.2.2.1 Evenimente i delegai. Soluii cu proiecte multiple


In momentul cnd utilizatorul face click pe buton, acesta ar trebui s execute o aciune n clasa container
(clasa care-l conine, in cazul nostru clasa Form1 ce instaniaz acel buton). Dar evident, butonul nu tie
nimic despre clasa container, el este un obiect din biblioteca .NET i este instaniat n mii de aplicaii de
tipul "Windows Form".
Tot ce poate s fac un buton n momentul cnd user-ul face "click", este s lanseze evenimentul "Click".
Daca este cineva s-l asculte (adic s-a scris o funcie care sa prind evenimentul), atunci aciunea click va
avea afect, altfel evenimentul se pierde n eter. Se poate face o paralel cu aciunile unui cael de paz.
Caelul de paz (ca i butonul), cnd se nate, nu tie unde va pzi i cine-l va asculta. Dac este pus s
pzeasc o vie de exemplu, tot ce poate el, este sa fac glgie, adic s emit evenimente (n cazul de
fa evenimentul "Thief_Inside"). Dac este cineva s-l asculte bine, dac nu, evenimentele se pierd.
Pentru a putea lansa i prinde evenimente, trebuie realizate cteva aciuni:
Definirea obiectulului "Delegate": reprezint amprenta funciei care trebuie sa prind acel
eveniment (echivalent cu un pointer la funcie din C clasic).
Definirea obiectulului "Event": este evenimentul propriu-zis.
Lansarea evenimentului
Prinderea evenimentului de functia "handler"
Toate aceste aciuni se fac automat de ctre VS n momentul cnd se face double-click pe un buton n
fereastra de design. VS-ul creeaz automat o funcie (handler) care sa trateze evenimentul trimis de buton
i tot ce avem noi de facut este s introducem cod n acea funcie. Dac ne uitm n background
(Designer.cs), observm c n acel fisier, VS-ul introduce cod pentru legarea evenimentului la funcie:

Putem defini i noi obiecte de tip Delegate i apoi s asociem evenimente la acetia pentru orice tip de
dialog ntre clase, nu neaprat clase de tip UI (User Interface).
De exemplu, dorim s afim un text n Form1 atunci cnd se creeaz o instan a clasei Person. In acest
sens, trebuie realizate urmtoarele modificri:
Modificarea clasei Person pentru a trimite evenimente n sistem:
Se definete un Delegate numit "MessageDisplayDelegate" n namespace-ul "namespace
OOP_Fundamentals" ce primete un string i nu returneaz nimic.
Se definete n clasa Person un eveniment static numit "MessageDisplayEvent"de tipul
acestui delegate.

Se adaug n constructorul clasei Person cod ce trimite evenimentul avnd ca mesaj


numele obiectului care se creeaz:

Version no.: 2

Page 40 of 83

Adugarea proiectului "OOP_Fundamentals" la referinele proiectului "Hello".


Cele dou proiecte realizate pna acum ("OOP_Fundamentals" i "Hello" ) sunt complet
independente, n sensul c, clasele definite ntr-un proiect, nu sunt vizibile n celalalt
proiect. Putem uni cele dou proiecte prin adugarea unuia ca referin la cellalt.Click
dreapta pe seciunea "References" din proiectul "Hello" i se alege opiunea "Add
reference". Din npua fereastra Se deschide tab-ul "Projects" i se selecteaz proiectul
"OOP_Fundamentals":

Din acest moment, toate clasele publice definite n acest proiect vor fi accesibile n
proiectul "Hello".

Trebuie doar ca namespace-ul "OOP_Fundamentals" s fie adugat la capitolul "using"


din header-ul fiecrei clase ce dorete utilizarea cmpurilor din "OOP_Fundamentals" .

Ataarea funciilor (Handler) la evenimente:

In acest moment, clasa Person trimite evenimente de tip "MessageDisplayEvent" pentru


orice obiect nou iniializat. Dac instaniem n clasa "Form1" un obiect de tip Person, ar
trebui s primim acest eveniment. Adugm o funcie care s fie apelat la primirea
evenimentului:

Version no.: 2

Page 41 of 83

Funcia se numete "void DisplayMessage(string text)" i trebuie s aib aceeai semntur


definit n delegatul "MessageDisplayDelegate". Funcia deschide un MessageBox ce afieaz textul
primit ca parametru:

Lansarea evenimentelor:

Adaugm n clasa Form1 un nou button prin care s crem noi obiecte de tip Person
folosind constructorul ce trimite evenimentul:

In acest moment, la fiecare click pe acest buton, Form1 afieaz n MessageBox numele i
prenumele obiectului creat:

3.2.2.2 Handlere multiple


Putem ataa mai multe funcii care s trateze un anumit eveniment, nu obligatoriu n aceeai clas. De
exemplu, o clasa surs poate trimite un eveniment ce conine datele de msurare a unui senzor la un
moment dat. Acel eveniment se intercepteaz de clasa UI ce afieaz pe ecran valoarea primit, de clasa
ce salveaz n baza de date valorea, dar i eventual de o clas care s transmit pe internet valorile la un
server central.
S ataam de exemplu dou handler-e care s intercepteze evenimentul "button1.Click".

Version no.: 2

Page 42 of 83

Funcia "DisplayMessage" (observai c are acelai nume cu handler-ul evenimentului


"Person.MessageDisplayEvent", dar difer prin numrul i tipul parametrilor) creeaz o fereastr de
mesaje (MessageBox) ce afieaz un text pe ecran. Prima parte a textului afiat este construit din
proprietatea Text a obiectului care a trimis evenimentul (((Button)sender).Text ) dup ce a fost n prealabil
convertit la o clas de tip Button.
De ce am convertit obiectul sender la tipul Button? Pentru ca sa putem avea acces la proprietile i
funciile specifice acestei clase. Fr aceast conversie nu exist prea multe informaii disponibile despre
obiectul ce a trimis evenimentul.
Problema care se pune este ca programatorul trebuie s tie foarte bine ctre ce tip face conversia
obiectului sender. Acesta vine n parametrii functiei sub forma de object, adic este o referin la clasa
object, clasa din care deriveaz toate obiectele din C#. Fr cast-ul respectiv, nu putem avea acces dect
la metodele din clasa object:

Proprietile clasei "Object" n comparaie cu proprietile aceluiai Object convertit la tipul


"Button"
In figura de mai sus sunt prezentate cele dou situaii: metodele disponibile din clasa printe object i
metodele aceluiai obiect sender dup ce a fost convertit la clasa derivata Button.
Noi tim c evenimentul este lansat de obiectul Button1, de aceea am convertit sender-ul la tipul Button.
Dar ce se ntmpl dac convertim sender-ul la un alt tip , de exemplu la tipul TextBox i s afim
proprietatea Text pentru acest sender de tip TextBox?

Version no.: 2

Page 43 of 83

Eroare de conversie de tip "Cast" aprut la rularea programului


Eroarea apare abia la rularea programului, cnd evenimentul se produce efectiv i atunci realizeaz
interpretorul c de fapt, sender-ul care a produs evenimentul este un obiect de tip Button pe care noi
dorim s-l convertim la un TextBox, ceea ce evident produce eroare.
Evident, c putem ocoli aceste tipuri de erori aprute n timul rulrii. Orice obiect afieaz o funcie
"GetType()" prin care se poate afla tipul obiectului n momentul execuiei. Si aceasta, chiar dac acel obiect
este de tipul "Object", pentru ca funcia este de tipul virtual n clasa de baz i suprascris n clasa derivat.
Se observ c s-a utilizat delegate-ul standard " public delegate void EventHandler(object sender,
System.EventArgs e)" definit n biblioteca Systems pentru interceptarea evenimentului "Click". Acest
delegate definete o funcie ce primete doi parametri: sender-ul i argumentul evenimentului (EventArgs).
O bun practic n sfera programrii C# presupune ca fiecare delegate s includ cele dou cmpuri.

3.2.3 Concluzii
In acest subcapitol am vzut cum se construiete o aplicaie Windows n C#, cum se insereaz controale n
form i interaciunea cu aceste controale (interceptarea evenimentelor), am vorbit despre funcia
InitializeComponent scris automat de VS, despre clasa MessageBox, despre delegai i evenimente.
In continuare vom dezvolta o nou form care sa prezinte ctre utilizator o interfa grafic de introducere a
datelor specifice unui student: nume, prenume, localitate, forma de cazare in camin, media, etc.
Prin intermediul acestei aplicaii vom nvaa cteva controale vizuale frevent ntlnite n majoritatea
aplicaiilor Windows: controlul TextBox, CheckBox, GroupBox, RadioButton, ListBox, Timer, ProggresBar
i vom mai vedea.

Version no.: 2

Page 44 of 83

3.3 Utilizarea controalelor standard n VS.NET


In acest capitol vom nva cteva controale (clase de obiecte) disponibile n mediul VS.NET i utilizate n
mod frecvent de marea majoritate a aplicaiilor de tip GUI (Graphic User Interface). Aceste controale sunt
grupate n fereastra "Toolbox" vizibil n stnga ecranului atunci cnd programatorul deschide fereastra
"Design" a formei:

Pornim un nou proiect numit "StudentView" n care dezvoltm o form unde vom insera cmpurile necesare
pentru vizualizarea i introducerea datelor specifice unui student. Forma "Form1.cs" creat automat de VS
se redenumete "StudentView", iar la referine se adaug proiectul "OOP Fundamentals" pentru a putea
utiliza clasa "Student" definit n acest proiect.

3.3.1 Controlul TextBox


Caseta de text se utilizeaz pentru introducerea de informaii de la tastatur sub form de text. Este un
mini-editor de text n sensul c permite o mulime de faciliti ntlnite ntr-un editor de text obinuit:
copy/paste, delete, scroll bar, scriere pe mai multe rnduri, etc.
Principalele proprieti ale unei casete de text sunt rezumate n urmtoarele:
Name: toate obiectele dintr-un program au un nume cu care pot fi identificate i manipulate;
Text: reprezint textul inserat n editorul respectiv (este dat sub forma de string);

Version no.: 2

Page 45 of 83

BackColor/ForeColor: culorile de fundal i de text pentru caseta respectiv;


BorderStyle: stabileste tipul marginii de caset, sunt disponibile 3 variante: None (fr bordur),
FixedSingle (caseta are bordur simpl), Fixed3D (bordura n relief);
Autosize : True/False: dac mrimea casetei se ajusteaz automat n funcie de coninutul su;
Multiline: precizeaz dac textul din caseta poate fi afiat pe mai multe rnduri;
Cursor: stabilete forma cursorului cnd acesta se afla deasupra casetei de text;
Enabled: dac este True atunci utilizatorul poate modifica coninutul textului, altfel textul este
protejat la scriere;
ScroollBars: stabilete barele de derulare aferente casetei:
o none: fara scroll;
o Horizontal: scroll orizontal sub caseta de text
o Vertical: scroll vertical
CharacterCasing:
o Lower: toate caracterele vor fi convertite la minuscule, indiferent de cum au fost
introduse;
o Upper: toate caracterele sunt majuscule;
o Normal: caracterele sunt nemodificate;

In forma "StudentView" vom insera controale de tip TextBox pentru patru cmpuri de informaii necesare n
descriere studentului: nume (tbSurname), prenume (tbName), localitate (tbCity), media (tbAverage):

In partea de jos a formei s-a introdus un TextBox (tbView) de tip ReadOnly Multiline cu ScrollBar vertical n
care se vor afia toate informaiile inserate n cmpurile formei. Aceste informaii vor fi refresh-ate la fiecare
click pe butonul Vizualizare Informatii (bView).
Indiferent de cmpul n care se afl focus-ul, dorim ca tasta Enter s acioneze butonul bView, astfel
nct, dup orice modificare, utilizatorul sa poat da Enter pentru a vedea rezultatul operaiunii. Ataarea
unui buton de tasta Enter se face din proprietatile formei. Una din aceste proprieti se numete
AcceptButton pe care noi o setm la butonul bView.

3.3.1.1 Validarea informaiilor din TextBox

Version no.: 2

Page 46 of 83

La preluarea datelor de la utilizator trebuie sa ne asigurm c acestea nu conin erori de introducere. De


exemplu, media studentului trebuie sa fie un numr cuprins ntre 1 i 10. Deci sunt dou verificari ce trebuie
efectuate:
textul introdus sa fie un numr valid (fr litere sau alte caractere diferite de cifre)
numrul nu depaete limitele impuse
Verificarea ar fi bine s se fac automat, chiar la prsirea cmpului tbAverage, astfel nct, utilizatorul s
fie ntors la editarea cmpului pn introduce date valide. Aceast verificare automat se face pe
evenimentul Validating asociat controlului tbMedie. Evenimentul se produce cnd se prsete textbox-ul
i are loc operaia de validare a textului scris n acesta.

S-a utilizat metoda tbMedie.Focus() pentru a aduce mouse-ul n cmpul tbMedie semnaliznd astfel
utilizatorului care este cmpul cu informaia greit.

3.3.2 Controlul ToolTip


VS-ul permite ataarea diverselor mesaje (ToolTip) de un anumit control din form. Introducem o nou
funcie "MyInitialization" alturi de "InitializeComponents" n care s iniializm i alte compinente din form,
cum ar fi de exemplu, acest ToolTip:

Recapitulare: n acest subcapitol s-a prezentat controlul TextBox cu principalele sale proprieti. Am
deschis un nou proiect n care s-au inserat cteva TexBox-uri pentru introducerea datelor despre un student
i un TextBox multiline pentru afiare. Am aratat cum se pot verifica automat datele dintr-un cmp oarecare
i cum se ataeaz un buton de tasta Enter.

Version no.: 2

Page 47 of 83

3.3.3 Controlul CheckBox (caseta de validare)


CheckBox-urile (casete de validare) sunt utilizate pentru afiarea (sau introducerea) datelor de tip boolean
ce pot lua doar dou valori true/false. In cazul nostru sunt necesare aceste CheckBox-uri pentru
semnalizarea unor situaii n care se afl studentul: este cazat sau nu la cmin, primete sau nu burs, este
sau nu integralist, etc.

Am adaugat doua CheckBox-uri , cbCazare cu textul Cazat in camin si cbBursa cu textul = Primeste
bursa. Functia bVizualizare_Click s-a modificat pentru a completa informatiile despre student si in functie
de aceste doua controale nou introduse:

In afar de proprietile comune tuturor controalelor (BackColor, Text, Font, etc) la CheckBox ne
intereseaz proprietatea Checked care ne spune starea controlului: true/false. In funcie de aceast stare,
n cmpul "tbView" se insereaz informaii referitoare la cazarea n cmin i la bursa studentului.

3.3.4 Controlul RadioButton (buton radio)


Acest control permite selecia unei opiuni din mai multe posibile. Orice selecie a unei opiuni le exclude
automat pe celelalte. Controalele de tip radio sunt grupate ntr-un cadru ce definete starea de excludere
reciproc a butoanelor incluse.
Vom continua proiectul cu adugarea a trei butoane radio care s specifice tipul bursei primita de student:
burs de studii, burs social, burs de performan.

Version no.: 2

Page 48 of 83

Cele 3 butoane radio sunt incluse intr-un GroupBox cu textul Tip bursa. Acest grup este initial invizibil
pn cnd se ajunge la un student care primete burs. Cnd se activeaz CheckBox-ul chBurse, grupul
radio trebuie sa devin vizibil pentru ca utilizatorul s poat selecta tipul de burs primit de studentul n
cauz. In acest scop se adaug un event-handler pe evenimentul chBurse_CheckedChanged care s
rezolve acest task:

Iar n funcia de vizualizare se adaug cod care s trateze cazul celor trei butoane radio:

Recapitulare: s-au prezentat cele dou controale ce pot lua valori de tip True/False: CheckBox si
RadioButton. RadioButton-ul permite o singur selecie dintr-un grup de opiuni, n timp ce CheckBox-ul
lucreaz independent de prezena altor controale. Proprietatea de baz a acestor controale este "Checked"
care returneaz True/False n funcie de starea butonului.

Version no.: 2

Page 49 of 83

3.3.5 Controlul ComboBox (list ascuns)


ComboBox-ul reprezint o list de elemente din care utilizatorul poate s-i selecteze linia care-l
intereseaz. Este util n cazul cnd utilizatorul trebuie s aleag o opiune din mai multe posibile, similar
cu RadioButton-ul, dar ComboBox-ul ocup mai puin spaiu la un numr mare de opiuni. In plus,
ComboBox-ul permite adugarea, tergerea unor elemente fr s afecteze design-ul formei.
Vom transforma TextBoxul tbCity ntr-un ComboBox (cbCity) n care se va insera localitile din care
provin studenii. Astfel, la introducerea unui student, utilizatorul primete o list de localiti din care
selecteaz localitatea de domiciliu a studentului. Avantajul fa de TextBox este dat de faptul c nu mai
trebuie introdus acelai nume de localitate de mai multe ori (cu posibilitatea de a tasta greit numele
localitii), odat introdus o localitate, ea va fi gasit n lista i selectat.
Pentru nceput populm acest ComboBox cu cteva localiti din jude: n fereastra StudentView.cs[Design]
selectm controlul cbCity i completm proprietatea Items (Collection):

In noua versiune a programului, utilizatorul face click pe ComboBox i se desfoar lista cu localitile
inserate pn n acel moment:

Afiarea localitii selectat din ComboBox se face prin apelul proprietatii Text :
tbView.Text += string.Format("\r\nLocalitate: {0}", cbCity.Text);
Dar ce facem dac apare un student dintr-o localitate care nu este n list? In acest caz, utilizatorul poate
scrie n ComboBox noua localitate, iar aceasta va aprea n proprietatea Text a controlului. Totui e destul
de incomod s tot introducem aceeai localitate n ComboBox ori de cte ori mai gsim un student din
localitatea nou introdus. E mai simplu s inserm localitatea n list ca s-o putem utiliza mai trziu. Pentru
aceasta, definim dou butoane n forma (bAdd, bDel) care s ne permit adugarea, respectiv tergerea de
localiti din list:

Version no.: 2

Page 50 of 83

Nu putem aduga o localitate n list dac ea exist deja. De aceea, nainte de adugare, se parcurge toat
lista de localiti i se verific ca noua localitate s nu existe n lista. Verificarea nu trebuie s in cont de
litere mari sau mici (case sensitive), dac exist "Iasi" n list i noi vrem s adugm "IASI", funcia de
verificare trebuie sa dea mesaj de eroare. Funcia "ToUpper()" aduce toate caracterele la litere majuscule
i anuleaz astfel diferena dintre "Iasi" i "IASI" sau "IAsi", etc.
Stergerea unei localiti din list se face simplu: apelm funcia Remove din colecia Items coninut de
list:

Recapitulare:
s-a prezentat controlul ComboBox ce este o list din care putem selecta un anumit articol sau putem
aduga altele noi. Lista este format dintr-o colecie de obiecte numit "Items" ce pstreaz informaii
despre datele stocate n list, numrul lor, etc;
s-au prezentat metode pentru adugarea unui item sau tergerea sa din list

Version no.: 2

Page 51 of 83

4 Salvarea datelor de lucru


4.1 Salvarea datelor n fiier
Aplicaia StudentView lucreaz foarte bine att timp ct programul ruleaz, toate localitile adugate n
list n timpul rulrii programului pot fi vizualizate i refolosite. Dar daca am nchis programul i revenim
mine la servici, observm ca lista de localiti este iarai la valoarea iniial, setat de noi n fereastra de
Design. Toate localitile adugate de utilizator pe parcursul rulrii programului s-au pierdut. Acest lucru
este normal, pentru c lista este un simplu obiect din form care se instaniaz n memorie la ncrcarea
formei, adugam n el localiti ce sunt salvate n memoria alocat acestui obiect, dar la nchiderea formei,
toate obiectele dispar cu tot ce s-a ncrcat n ele. Rmn doar localitile introduse de noi prin proprietatea
Items i care sunt hardcodate n funcia InitializeComponent().
Singura soluie de memorare a localitilor nou introduse este de a salva coninutul listei ntr-un fiier pe
disc la nchiderea programului i citirea acestuia de pe disc la ncrcarea formei.
Scrierea/citirea informaiilor pe disc reprezint un task relativ dificil, dar VS pune la dispoziia
programatorilor clasa System.IO.File ce include metode puternice i uor de utilizat pentru lucrul cu
dispozitivele de stocare a informaiei.
Crearea unui fiier text este foarte simpl cu ajutorul acestei clase i include urmtorii pai:
deschiderea fiierului (functia File.CreateText) n care se salveaz datele (eventual crearea
acestuia dac nu exist);
scrierea datelor n fiier (funcia WriteLine);
nchiderea fiierului (Close ).
Vom aduga un handler la evenimentul "FormClosing" care s salveze n fiierul localitati.txt de pe
directorul curent toate localitile inserate n lista cbCity:

Observaii:
denumirea fiierului s-a introdus ca un string constant (const string FILE_NAME = "localitati.txt";),
const nseamn c acest string nu poate fi modificat n decursul programului;
scrierea datelor n fiier se face cu obiectul "StreamWriter" returnat de funcia
"File.CreateText(FILE_NAME);"

Version no.: 2

Page 52 of 83

se parcurge toat lista de localiti i fiecare localitate va ocupa un rnd din fiierul text scris pe disc
(sw.WriteLine(cityItem.ToString());). Nu ntotdeauna liniile din ComboBox conin stringuri, de
aceea trebuie convertit la string fiecare item din list.
evident, orice acces la un fiier pe disc trebuie facut ntr-o schem try...catch...finally care se ncheie
cu instruciunea de nchidere a fiierului dac acesta este deschis (n caz contrar fiierul nu mai poate fi
accesat de alte aplicaii sau de aceeai aplicaie n alta instan):
if (sw != null)
{
sw.Close();
}

4.1.1 Citirea datelor din fisier


La fel de bine trebuie creat un handler care s citeasc datele din fiier i s le pun n list. Se ataeaz la
evenimentul "Load" a formei "StudentView" urmtoarea funcie:

Se creeaz de data aceasta un obiect de tip "StreamReader " cu care se deschide fiierul i se citesc liniile
din acesta. Lista cbCity este golit n prealabil (cbCity.Items.Clear();), dup care se parcurge fiierul
(while ((line = sr.ReadLine()) != null)) i fiecare linie din fiier va forma un item n
ComboBox (cbCity.Items.Add(line);).
Recapitulare:
informaiile adugate ntr-un ComboBox se pierd la ieirea din program, de aceea s-au dezvoltat
funcii care s salveze i s citeasc aceste informaii din fiiere. Cu aceast ocazie s-au prezentat clasele
File , StreamReader i StreamWriter;

Version no.: 2

Page 53 of 83

4.2 Serializare
Am vzut c avem la dispoziie clasele "File", "StreamWriter", "StreamReader" cu care s salvm n fiier
iruri de caractere. Totui, dac vrem s salvm toate datele specifice unui student aceste clase nu prea
ajut. Este mai uor s salvez aceste date ntr-o clas i apoi s salvez ntreaga clas ca un tot unitar.
In acest scop putem folosi Serializarea, o tehnic ce permite salvarea pe disk a obiectelor complexe care
includ att iruri de caractere, ct i metode, componente de diverse tipuri (din care unele pot fi la rndul lor
alte obiecte).

4.2.1 Salvarea informaiilor n clasa Student


Este util ca toate informaiile ce in de un student s fie salvate ntr-o singur obiect, iar acesta s fie trimis
ca referin ctre toate clasele ce prelucreaz informaiile respective.
Butonul 'bView" folosit pentru vizualizarea datelor va fi folosit i pentru salvarea acestora ntr-un obiect de
tipul "Student". Acel obiect va fi mai departe salvat pe disc prin serializare, trimis ctre o baz de date, etc.
Se declar un obiect de tipul Student n clasa "StudentView", iar acel obiect va fi iniializat n funcia
"bView_Click" prin apelarea metodei "private void FillStudent()". In acest fel, utilizatorul
verific n ferestra de jos datele studentului i n acelai timp completeaz i cmpurile obiectului de tip
Student:

4.2.2 Serializarea clasei Student


In acest context ne trebuie o clas ce primete un obiect dintr-o clas oarecare, l salveaz pe disc, urmnd
ca la un moment dat, s putem citi obiectul de pe disc i s-l reconstruim n forma iniial. Acest proces de
salvare/citire a obiectelor pe disc se numete serializare/deserializare. VS-ul pune la dispoziia
programatorului clase i metode care permit memorarea obiectelor n fiiere folosind formatul XML-SOAP
(Simple Object Acces Protocol). Clasa "System.Runtime.Serialization.Formatters.Soap.SoapFormatter"
conine toate metodele necesare n serializarea sau deserializarea obiectelor.

Version no.: 2

Page 54 of 83

Problema e ca aceast clas nu se gasete n bibliotecile ataate implicit de VS, ea trebuie adaugat prin
mecanismul: Project/Add Reference... :

Se alege referina "System.Runtime.Serialization.Formatters.Soap" i se d click pe OK, iar aceasta va


aprea n capitolul "References" al proiectului:

In continuare vom aduga dou funcii care s salveze pe disc obiectul Student din forma curent, respectiv
s citeasc informaiile studentului din fiier i s le afieze n form.
Nu orice clas poate fi serializat, ci doar cele care au atributul [Serialize()] , n caz contrar, la serializare
apare eroarea:

Noi nu am declarat clasa "Student" cu acest atribut, deci o facem acum:


[Serializable] public class Student:Person, IStudent
Adugm cele dou butoane pentru citire/scriere a obiectului Student pe disc i funciile aferente:

Version no.: 2

Page 55 of 83

Funcia de scriere n fiier:

Funcia de citire din fiier i afiarea datelor n fereastr:

Version no.: 2

Page 56 of 83

Cele dou funcii apeleaz funcia privat de afiare a datelor dintr-un obiect Student primit ca parametru:

In caz c obiectul Student este null, atunci funcia terge toate cmpurile de afiare, pregtindu-le pentru
introducerea unui alt student.

Version no.: 2

Page 57 of 83

Dac totul decurge normal, pe disc n directorul curent se creeaz un fiier de forma:

n care se pstreaz toate datele referitoare la student.


Recapitulare:
n acest capitol s-au definit termenii de serializare/deserializare i s-a adaugat o nou referin la
proiectul n lucru (clasa necesar serializrii);
nu toate clasele se pot serializa, ci doar cele care au atributul [Serialize()] ataat. Astfel, clasele
String, ArrayList,.. pot fi serializate direct, dar clasa Student nu are acest atribut. La crearea unei clase noi
pe care vrem s o serializm se adaug acest atribut n definiia clasei (inclusiv pentru clasa printe).

Version no.: 2

Page 58 of 83

4.3 Salvarea informaiilor n baze de date


4.3.1 Ce este o baz de date
Am vazut n capitolul anterior c VS pune la dispoziia programatorilor instrumente puternice de salvare a
informaiilor de lucru n fiiere. Clasa File conine funcii de creare i de acces la fiiere de pe disc, iar prin
serializare/deserializare putem salva orice tip de obiect ce are proprietatea [Serializable()].
Totui, cnd avem un volum mare de informaii ce trebuie gestionate, aceste instrumente devin ineficiente.
Singura soluie viabil n gestionarea volumelor mari de informaii rmne un Sistem de gestionare a
bazelor de date (SGBD).
Baza de date este un serviciu ce lucreaz independent de programul nostrum, la care noi putem apela s
stocm informaii diverse n cantiti foarte mari, dup care s cerem aceste informaii conform unor criterii
i tehnici de filtrare. Dac lum ca exemplu activitatea didactic dintr-o unitate de nvmnt, atunci
constatm c ne trebuie o baz de date format din tabele n care s introducem informaiile specifice
acestei activiti:
un tabel studenti, n care s salvm pe linii detaliile pentru fiecare student din facultate;
tabele pentru grupe, ani colari, ani de studiu, specializri, domenii: n care s se salveze
structura organizatoric a facultii;
tabele pentru disciplinele studiate n facultate cu informaiile specifice: numr de ore de curs,
numr credite asociate disciplinei, lucrri de laborator sau seminar, etc.;
tabele pentru examene, note obinute de studeni la examene, sesiunile de examinare, etc.
etc
Tabelele nu sunt independente unele de altele,ntre ele exist relaii de legtur care s permit obinerea
de informaii complexe, culese din mai multe tabele legate prin aceste relaii. De exemplu, tabela studenti
este legat de tabela grupe (fiecare student apartine unei grupe ntr-un an scolar), mai este legata de
tabela discipline ( un student studiaza un anumit numar de discipline la un moment dat), de tabela note
n care s gsim notele acordate studentului respectiv, etc.
Avantajele utilizrii bazelor de date n construcia programelor de gestionare a informaiilor sunt evidente:
Baza de date primete o cantitate mare de informaii pe diverse ci i de la mai multi utilizatori
simultan, le stocheaz ntr-un depozit unic astfel nct, orice informaie introdus de un utilizator
este vizibil tuturor. De exemplu, dac un profesor a introdus n baza de date nota unui student
la disciplina asociat, secretara poate calcula media fr s fie nevoit s mearg la profesor ca
s cear notele studenilor. Cei doi utilizatori lucreaz n sedii diferite, cu aplicaii diferite, dar
informaia este vizibil tuturor.
Baza de date dispune de mecanisme puternice de extragere a informaiilor complexe. Pe baza
limbajului SQL (Structured Query Language) utilizatorul scrie instruciuni de selecie a datelor din
mai multe tabele simultan i conform unor criterii de filtrare performante. Astfel, pot cere de
exemplu bazei de date (cu ajutorul unei instruciuni SQL), s-mi dea studentul cu media cea mai
mare din grupa 6304 la disciplina Masurari Electrice n sesiunea de var 2007.
Accept deschiderea mai multor sesiuni de lucru simultan, astfel nct pot lucra diveri utilizatori
(unii introduc date, alii vizualizeaz, alii modific), fr s se blocheze unul pe cellalt.
Baza de date este independent fa de aplicaiile care o utilizeaz, unii utilizatori introduc date
printr-o interfa realizat n Oracle Forms, alii printr-un program dezvoltat n VS.NET, alii
vizualizeaz date prin Oracle Reports, sau Crystal Reports, sau pur i simplu, printr-un editor
SQL. Fiecare ii deschide o sesiune de lucru specific prin care are acces la toate informaiile
din baza de date.
Sunt mai multe servere de baze de date (SGBD) pe piaa de software: Oracle, SQL Server, MySql, SQLite,
Acces, FoxPro, etc. Utilizatorul alege SGBD-ul care satisface cel mai bine compromisul ntre performan i
pre. In continuare vom lucra cu o baz de date SQLExpress, fiind o baz cu performane deosebite la un
pre de cost rezonabil.

Version no.: 2

Page 59 of 83

4.3.2 Instalarea bazei de date

Ne conectm la site-ul Microsoft de unde downloadm kit de instalare a serverului SQLExpress ce


este distribuit gratuit de firma respectiv (atenie: trebuie s avei VS 2008 SP1 instalat n
calculator).
https://www.microsoft.com/betaexperience/pd/SQLEXPDB32/enus/

Instalm serverul SQLExpress ce va funciona sub form de serviciu Windows, l putem verifica
deschiznd fereastra de servicii din ControlPanel/AdministrativeTools:

Deschidem programul "Microsoft SQL Server Management Studio" ce vine automat cu acest
SQLExpress i n cadrul acestui program crem o nou baz de date numit "Student" (alegem
folderul de instalare "D:\StudentDatabase" pe care-l crem n prealabil).

In urma acestei operaii se vor crea n folderul respectiv dou fiiere ce vor conine informaiile din baza de
date: "Student.mdf" i "Student_log.ldf".

4.3.3 Crearea tabelelor

Click dreapta pe folderul "Tables" din baza Student i se alege opiunea "New Table":

Version no.: 2

Page 60 of 83

Se creeaz tabela "Ani_Universitari" cu urmtoarele coloane:


o Pk_an_universitar: tip "int", primary key, autoincrement (Is identity, Identity increment=1):

o
o

Cod_an_universitar: nchar(20), not null;


Descriere_an_universitar: nchar(50)

Se creeaz tabela "Grupe" cu urmtoarele coloane:


o Pk_grupa: tip "int", primary key, autoincrement (Is identity, Identity increment=1):
o Cod_grupa: nchar(20), not null;
o Descriere_grupa: nchar(50)
Tabela "Studenti" cu urmtoarele coloane:
o Pk_student: tip "int", primary key, autoincrement (Is identity, Identity increment=1):
o Nume_student: nchar(50), not null;
o Prenume_student: nchar(50), not null;
o Adresa: nchar(50);

Tabela "Studenti_Grupe": este tabela de legtur ntre studeni i grupe. In fiecare an universitar,
fiecare student se nscrie la cte o grup (grupa din anul superior dac este promovat, sau aceeai
grup dac rmne repetent). Aceast tabel conine informaiile despre student specific unui an
universitar: la ce grup este, numr de credite, medie obinut.
Coloanele sunt urmtoarele:
o Pk_student_grupa: tip "int", primary key, autoincrement (Is identity, Identity increment=1):
o Pk_student: face legtura la pk_student din tabela studeni, specific n mod unic studentul;
o Pk_grupa: face legtura la pk_grupa din tabela grupe, specific n mod unic grupa;
o Pk_an_universitar: specific n mod unic anul universitar n curs;
o Credite: tipul float, memoreaz numrul de credite obinute de student n anul universitar
current

Version no.: 2

Page 61 of 83

o Medie: tipul float, reprezint media studentului pe acel an universitar


Se salveaz tabelele i se dechide fereastra "Diagrams". In aceast fereastr utilizatorul poate
define legturi de tip "foreign key" ntre tabele. Aceste legturi verific ca nu cumva s se insereze
o linie ntr-o tabel copil ce nu corespunde unei linii din tabela printe. De exemplu, nu putem
introduce n tabela "Studenti_grupe" o valoare "pk_student" ce nu exist n tabela Studenti.
Se definesc urmtoarele relaii:
o Fk_studenti_grupe_studenti: leag pk_student dintre tabelele Studenti i Studenti_Grupe.
Click dreapta pe tabela Studenti_grupe i se alege opiunea "Relationships".In cadrul
acestei relaii se seteaz numele, precum i coloanele ce trebuie s corespund intre
tabela Student i tabela curent.

o
o

Fk_studenti_grupe_grupe: leag pk_grupa dintre tabelele Grupe i Studenti_Grupe


Fk_studenti_grupe_ani_univ: leag pk_an_universitar dintre tabelele Ani_Universitari i
Studenti_Grupe

In final, diagrama bazei de date "Student" ar trebui s arate conform figurii de mai jos:

Se introduc cteva linii de lucru n fiecare tabel pentru testarea funcionalitii:


insert into Ani_universitari(cod_an_universitar, descriere_an_universitar)

Version no.: 2

Page 62 of 83

values('2011-2012','anul 2011-2012');
insert into Ani_universitari(cod_an_universitar, descriere_an_universitar)
values('2012-2013','anul 2012-2013');
insert into Studenti(nume_student, prenume_student, adresa)
values('Nume1', 'Prenume1','Iasi');
insert into Studenti(nume_student, prenume_student, adresa)
values('Nume2', 'Prenume2','Focsani');
insert into Studenti(nume_student, prenume_student, adresa)
values('Nume3', 'Prenume3','Pascani');
insert into Grupe(cod_grupa, descriere_grupa) values('6403','grupa 6403');
insert into Grupe(cod_grupa, descriere_grupa) values('6404','grupa 6404');
insert into Grupe(cod_grupa, descriere_grupa) values('6408','grupa 6408');
insert
Medie)
insert
Medie)

into Studenti_Grupe(pk_student, pk_grupa, pk_an_universitar, Credite,


values(11,1,1,45,9.40);
into Studenti_Grupe(pk_student, pk_grupa, pk_an_universitar, Credite,
values(12,1,1,30,8.15);

4.3.4 Salvarea obiectului "Student" n baza de date

4.3.4.1 Tehnologia ADO.NET


Un capitol important n cadrul platformei VS.NET este dat de tehnologia ADO (ActiveX Data Objects) de
gestionare a bazelor de date. ADO.NET reprezint o mulime de biblioteci de programe ce permit
interaciunea cu sistemele de stocare a datelor (baze de date, fisiere XML, Excel, etc.).
Arhitectura ADO.NET include trei componente principale:
o Baza de date: este suportul n care se stocheaz datele
o Data Provider (Furnizorul de date) : reprezint colecia de obiecte prin care ne conectam la
baza de date i operm modificari n ea;
o SQLCommand-ul: obiect prin care se execut instruciuni SQL asupra bazei de date
Parantez: SQL este un limbaj standard prin care putem comunica cu orice baz de date. El definete un
set de instruciuni pe care le inelege i le execut baza de date. Instruciunile sunt scrise ntr-un editor SQL
ce stabilete mai inti o conexiune cu baza (folosind cont si parola) i apoi trimite comenzile ctre aceasta.
Instruciunile pot fi pentru vizualizarea i modificarea datelor din tabelele bazei de date (select , update,
insert,), sau pentru modificarea structurii bazei (create table , drop, alter ).
Tot prin instructiuni SQL comunic i platforma .NET cu baza de date, dar de data aceasta, aceste
instruciuni sunt scrise si trimise prin intermediul controalelor puse la dispoziie de libraria ADO.NET.
Exist mai multe sisteme de stocare a datelor pe pia, fiecare folosind un protocol diferit de comunicaie,
de aceea ADO.NET dispune de cate un DataProvider pentru fiecare tip de baz de date:
o ODBC DataProvider: pentru baze de date mai vechi, ce folosesc protocolul ODBC
o OleDB DataProvider: pentru Acces, Excel,..;
o Oracle DataProvider: pentru baze de date Oracle;
o SQL DataProvider: pentru Microsoft SQLServer;

In acest capitol vom aduga codul surs necesar pentru salvarea obiectului "Student" n baza de date. Sunt
necesare urmtoarele etape:
Stabilirea conexiunii la baza de date

Version no.: 2

Page 63 of 83

Instanierea obiectelor de lucru cu baza de date: SQLConnection i SQLCommand


Definirea comenzii SQL de inserare a unuio student n tabela "Studenti"
Executarea comenzii SQL
Inchiderea conexiunii la baza de date

4.3.4.2 Stabilirea conexiunii la baza de date

Se adaug n soluia "OOP Course" un nou proiect de tip "Class Library" numit "DataStore". Class
Library c acest proiect este destinat de a fi utilizat de un alt proiect, nu conine clasa "Program",
deci nu poate fi lansat n execuie de sine stttor.
Se adaug la referinele acestui proiect proiectul "OOP Fundamentals" n scopul utilizrii clasei
Student deja definit acolo.
Click dreapta pe proiectul nou adugat i se selcteaz Properties/Settings.
Se definete un string de conectare la baza de date "Student":
o Alegem numele noului string de conectare ca fiind"ConnString", tipul este "Connection
string", iar la value facem click pe butonul "".
o Alegem "Data Source" de tipul "Microsoft SQL Server (SQLClient)
o Alegem "Use Windows Authentification": utilizatorul deja logat pe computerul respective are
acces direct la baza de date
o Din cadrul bazelor de date definite pe acest server alegem baza noastr "Student"
o Click pe "Test Connection" pentru a verifica dac conexiunea funcioneaz
In final se obine un nou string de conectare avnd valoarea "Data Source=WKSLUC\SQLEXPRESS;Initial Catalog=Student;Integrated Security=True" (bine, Data Source depinde
de numele calculatorului pe care este instalat baza de date).

Version no.: 2

Page 64 of 83

4.3.4.3 Funcia de salvare a obiectului "Student" n baza de date


In cadrul proiectului "DataStore" se adaug o clasa "DS_Student" ce conine o funcie static care primete
ca parametru un obiect din clasa "Student" i salveaz n baza de date acel obiect.
Codul funciei este dat n continuare:

Funcia conine urmtoarele componente:


Stringul "SqlCommandInsert" ce specific fraza SQL de inserare a unui student n baz. Fraza
include i anumii parametri (@surname,@name,@address) prin prin intermediul crora se
transmit informaiile pentru fiecare coloan din tabel.
Se creeaz un obiect de tip "SqlConnection" prin care se realizeaz conexiunea la baza de date.
Acest obiect primete ca parametru stringul de conectare pe care-l regsim n proprietile
proiectului "DataStore" (Properties.Settings.Default.ConnString) creat la punctul
anterior.
Se intr n seciunea try-catch (orice acces la o baz de date trebuie pus n try-catch deoarece
ntotdeauna este posibil ca baza de date s dea erori: serverul este oprit, sau valorile inserate nu
respect o anumit constrngere definit n baz, etc) unde se creeaz obiectul SqlCommand , se
ataeaz acestuia comanda SQL ce trebuie executat i se dau valori parametrilor.
In final se dechide conexiunea la baz, i se execut comanda SQL: cmd.ExecuteNonQuery().
Obligatoriu trebuie inserat clauza Finally unde se nchide conexiunea, indiferent dac a fost sau
nu eroare n adugarea studentului.
Revenim la proiectul "StudentView" unde adugam un nou buton pentru salvarea datelor n baza de date.
Funcia ataat trebuie doar s apeleze metoda static DS_Student.AddStudent(currStudent) .

Version no.: 2

Page 65 of 83

Observm c apelul se face tot ntr-o construcie try-catch deoarece trebuie prinse erorile aruncate de
funcia apelat. Funcia "DS_Student.AddStudent" prinde excepiile, dar nu le afieaz pentru c nu
are cum. Ne amintim c proiectul "DataStore" este de tip "ClassLibrary", deci nu are ataat o interfa
grafic. Controlul "MessageBox" nici nu este disponibil n mod implicit n acest tip de proiect. Aceste
proiecte lucreaz n background, ele doar execut sarcini trimise din proiectele superioare, gen
"StudentView". Orice eroare produs n aceste procese de background trebuie trimis mai sus, pn ajunge
la proiectul de top unde se afieaz mesajul de eroare.

4.3.5 Afisarea dinamic a mesajelor. Controalele


StatusStrip i Timer
Orice tranzacie asupra bazei de date trebuie semnalizat utilizatorului, astfel nct, acesta s aiba un feedback asupra aciunilor sale (n funcia "bSaveDB_Click" am inserat dou MessageBox-uri prin care
afim rezultatul aciunii: studentul a fost inserat cu succes, sau respectiv cu eroare).
Dar folosirea abuziv a casetelor de dialog de tipul "MessageBox" poate fi deranjant pentru un utilizator
ce introduce un volum mare de informaii n baz. Utilizatorul vrea sa introduc ct mai rapid datele, s nu
fie agresat cu tot felul de mesaje de tipul "Adaugarea s-a efectuat cu succes" la care el s fie obligat s
acioneze butonul de nchidere a dialogului.
Este mai comod pentru el dac , dup fiecare aciune a sa , s apar n partea de jos a formei un mesaj de
la program despre modul de finalizare a aciunii, mesajul s apar pentru 2,3 secunde i apoi s dispar
singur. In felul acesta, utilizatorul se poate concentra asupra muncii de introducere a datelor i n acelai
timp, are i informaia despre rezultatul aciunii sale.
VS-ul deine un control specializat pentru afiarea mesajelor numit StatusStrip. Acesta se prezint ca o bar
de stare ce poate fi ataat la una din marginile ferestrei (implicit se afieaza n partea de jos) i conine
diverse alte controale de afiare a informaiei : StatusLabel, ProgressBar, DropDownButton, SplitButton.
In acelasi timp ne trebuie un control care s msoare timpul de afiare a mesajului, iar cnd acesta s-a
terminat, s anuleze mesajul. Pentru msurarea timpului folosim controlul "Timer", ce este un cronometru
care se incrementeaz la fiecare milisecund. Are dou proprieti de lucru i un eveniment asociat:
Enabled: True/False : se pornete sau se oprete cronometrul
Interval: numrul de milisecunde la care cronometrul trebuie s dea alarma
Tick: este evenimentul lansat de Timer cnd s-a expirat timpul setat de proprietatea Interval.
Se deschide fereastra ToolBox i se alege controlul TimerControlul prin operaia drag&drop. Se seteaz
numele "timerStatusStrip" i se asociaz funcia "timerStatusStrip_Tick" la evenimentul "Tick"
trimis de acesta. Timer-ul nu apare n interfaa cu clientul deoarece el nu este un control vizual, el este doar
un obiect n spatele scenei ce msoar timpul i emite evenimentul "Tick" la fiecare interval de timp stabilit.
Totui, el se vede n faza de dezvoltare a formei n partea de jos a ferestrei:
.

Version no.: 2

Page 66 of 83

Se adaug de asemenea la forma StudentView un control de tip StatusStrip numit "statusStripView" la care
se adaug un control de tip label numit "statusStripLabel" folosit pentru afiarea mesajelor.
In continuare vom scrie o funcie care primete ca parametri mesajul ce trebuie afiat i timpul de afiare,
iar funcia va afia mesajul n StatusStrip.

La fiecare apel al funciei se pune mesajul n "statusStripLabel" i se pornete ceasul cu intervalul


stabilit. La terminarea intervalului se terge mesajul i se oprete ceasul.
Recapitulare: am studiat n acest capitol o modalitate de a salva informaiile din clasa StudentView ntr-o
baz de date:
Am definit baza de date
Am creat tabelele de stocare a informaiei
Am creat clasa "DataStore" pentru accesul la baza de date. In aceast clas am definit obiectele
SQLConnection i SQLCommand.
Am artat cum se creeaz stringul de conectare la baza de date i cum se stocheaz n setrile
proiectului
Am creat un buton n StudentView pentru salvarea datelor n baz specificnd modul de
transmitere i afiare a erorilor
Am introdus controlul StatusStrip pentru afiarea mesajelor de lucru

Version no.: 2

Page 67 of 83

5 Aplicaia "E-Student"
In acest capitol vom finaliza aplicaia construit pe parcurs, prin adugarea unor noi faciliti absolut
necesare ntr-o aplicaie de gestionare a informaiilor referitoare la studeni:
Adugarea, modificarea sau tergerea unui student din baza de date
Afiarea studenilor pe grupe i ani universitari n tabele de tip DataGrid
Funcia de cutare a unui student
...
Pe parcurs vom introduce noi clase sau controale necesare n implementare aacestor funcionaliti: colecii
de obiecte, controale de afiare tabelar, progress bar, etc.

5.1 Colecii de obiecte


Forma noastr de pn acum merge foarte bine dac lucrm cu un singur student. Dar practica este
complet alta, n realitate trebuie sa introducem i s salvm date despre o mulime de studeni. Avem deci
nevoie de o clas n care s putem insera mai multe obiecte de tip student i clasa s-mi ofere posibiliti
de inserare, tergere, etc.
Un prim pas n gruparea obiectelor este tabelul utilizat i n programarea clasic C (de exemplu int[]
values = {1, 2, 3, 4};), dar acesta este o simpl colecie de obiecte de acelai tip care se pot
accesa printr-un index. Adugarea/eliminarea unui obiect dintr-un tabel este o operaie greoaie i trebuie
fcut de programatorul care utilizeaz tabelul.
In schimb, se poate utiliza clasa "ArrayList" din libraria "System.Collection" ce permite adugarea/tergerea
n mod dinamic a elementelor, obiectul de tip ArrayList se redimensioneaz automat la modificrile aduse n
timpul execuiei programului. In plus n colecie se pot insera obiecte de tipuri diferite.
Metodele de lucru ale clasei "ArrayList" sunt urmtoarele:
Add: adaug un obiect n list;
Remove: terge din list obiectul primit ca parametru
RemoveAt: terge din list obiectul de un indice dat.
Find: caut un obiect dintr-o list pe baza unei funcii de comparare date
Accesul la obiectele din list se face prin indici, primul element din list avnd indicele zero. Coleciile de
obiecte suport de asemenea instruciunea "foreach" prin care se poate baleia toate elementele din list.
O alt clas din librrie se refer la o colecie de obiecte de acelai tip, dar tipul este definit in timpul crerii
coleciei, sunt aa numitele "colecii generice" ( System.Collections.Generic.List<T>). Putem crea cu
ajutorul acestei clase colecii de orice tip (string, Student, etc):
S facem un mic exemplu n clasa "Program" din proiectul tip consol pentru a verifica aceste
funcionaliti:

S-a definit o colecie de tip "Student" numit "myStudentList" la care s-au adugat 3 studeni. Prin
instruciunea "foreach" s-au afiat toi studenii din list, iar prin apelarea funciei "Find" s-a cutat studentul

Version no.: 2

Page 68 of 83

"Stud1" n list. Funcia "Find" trebuie s primeasc un delegate (un pointer la o funcie) care tie cum s
compare dou obiecte din clasa "Student" (cazul de fa s-a cutat un student dup nume).
Acest cod de program produce urmtoarea ieire la consol:

5.2 Citirea listelor de studeni din baza de date


In continuare vom aduga n clasa "DS_Student" o nou funcie ce primete ca parametri anul universitar,
precum i numrul unei grupe i returneaz lista cu toi studenii din acea grup nscrii n acel an
universitar.

Sunt folosite aceleai obiecte descrise n funcia "AddStudent". In plus s-a definit un nou obiect de tip
"SqlDataReader" n care s-au salvat toate informaiile aduse de fraza "select" din baza de date. Acest
obiect conine funcia "Read" prin care se baleiaz toate liniile coleciei, iar pe fiecare linie se acceseaz
coloanele aduse de fraza "select" prin intermediul construciei "reader["nume_coloana"]".
Pentru fiecare linie din colecia din reader se creeaz un obiect de tip "Student" (currStudent) ce se adaug
la lista "studentList" (studentList.Add(currStudent);).

Version no.: 2

Page 69 of 83

5.3 Forma "E-Student"


Dorim s construim o form care s vizualizeze studenii sub forma unui grid, avnd posibilitatea s
modificm datele unui student, s tergem sau s adugm un nou student. Forma va afia studenii
selectai dup ani universitari i grupe:

5.3.1 Afiarea anilor universitari


Anii universitari vor fi afiai ntr-un ComboBox, iar selecia unui anumit an va conduce la refresh-area
celorlalte controale. Toat informaia afiat n form depinde de anul universitar selectat.
Similar cu controlul "cbClass", se creeaz un alt ComboBox ce va fi populat cu informaiile citite din tabela
"ani_universitari" din baza de date.
Trebuie parcuri urmtorii pai:
Definirea clasei "DS_Year" n proiectul "DataStore", clas ce conine proprieti pentru cele trei
informaii ce descriu un an universitar: PK, cod, descriere.

Construirea funciei "List<DS_Year> GetYearList()" ce returneaz o list cu toi anii gsii n


baza de date. Funcia se definete chiar n interiorul clasei "DS_Year" i este similar cu funcia
"GetStudentList" prezentat mai sus.

Version no.: 2

Page 70 of 83

Ataarea listei la controlul ComboBox ("cbYear"). Controlul ComboBox permite definirea liniilor
direct n colecia "Items", dar de asemenea, pot s-l populez cu date n mod dinamic prin ataarea
lui la o list citit din baz (DataSource = yearList):

ComboBox-ul are dou componente:


- "DisplayMember" este proprietatea care se afieaz sub form de text;
- "ValueMember" este valoarea pe care o returneaz controlul.
In cazul nostru, afim codul grupei, dar valoarea de care avem nevoie este PK-ul anului universitar. Cu
acest PK putem gsi n continuare grupele ce au studeni n acest an universitar i mai departe studenii ce
aparin grupei selectate n cellalt ComboBox.

5.3.2 Afiarea grupelor


Pentru grupe inserm un ComboBox pe care-l atam de lista grupelor gsite n baza de date. Urmtorii
pai trebuie parcuri:
Definirea clasei "DS_Class" n proiectul "DataStore", clas ce conine proprieti pentru cele trei
informaii ce descriu o grup: PK, cod, descriere.

Version no.: 2

Page 71 of 83

Construirea funciei "List<DS_Class> GetClassList(int pkYear)" ce returneaz o list cu


toate grupele gsite n baz pentru un an universitar dat.

Ataarea listei la controlul ComboBox ("cbClass").

5.3.3 Popularea automat a listelor de tip ComboBox

Version no.: 2

Page 72 of 83

Doresc ca atunci cnd selectez un an universitar, lista grupelor afiate s se modifice automat, afind doar
grupele ce au studeni n acel an universitar. De asemenea, pentru fiecare grup selectat s se afieze
automat studenii din acea grup i acel an universiar.
In acest scop, interceptm evenimentul "SelectedIndexChanged" al fiecrui ComboBox:

Iar ComboBox-ul de la care pornesc toate afirile l populez chiar n constructorul clasei:

5.3.4 Afiarea studenilor. Controlul DatGridView


Studenii sunt mult mai muli, nu pot fi afiai folosind ComboBox sau TextBox. Cel mai indicat control pentru
afiarea datelor complexe este "DataGridView". Acest control este un grid cu linii i coloane ce se poate
ataa la o list de obiecte (n cazul nostru, o list de obiecte "Student". Proprietile obiectului "Student" vor
deveni coloane n data grid, iar informaiile dintr-un obiecte vor forma o linie in grid.
Este un control foarte complex, dar uor de utilizat pentru afiarea datelor. Pune la dispoziie o mulime de
proprieti prin care putem modifica aspectul gridului, dar i o mulime de evenimente prin care putem
rspunde la aciunile utilizatorului.
Urmtoarele aciuni trebuie ndeplinite pentru a face un grid funcional:
Instanierea controlului "DataGridView": se aduce un datagrid din toolbox i se poziioneaz n
form (numele obiectului va fi "dgStudent"). Automat, funcia "InitializeComponents" va include
toate liniile de cod necesare iniializrii acestui control complex.
Ataarea gridului la lista de obiecte ce trebuie afiate: se alege proprietatea "DataSource" i se
merge pe opiunea "Add Project Data Source...":

Noua surs de date va fi de tip "Object" i se alege din namespace-ul "OOP_Fundamentals" ca fiind clasa
"Student".

Version no.: 2

Page 73 of 83

Observaie: dac nu apare acest namespace, nseamn c nu ai adugat proiectul "OOP_Fundamentals"


la capitolul "References". Adugai proiectul mpreun cu celelalte: "DataSource" i "StudentView". Noul
nostru proiect numit "E-Student" se situeaz n topul tuturor, adic va utiliza clasele definite n proiectele
inferioare. Nu se poate face referire dect ntr-un sens, dac proiectul 1 face referire la proiectul 2, atunci
proiectul 2 nu va putea aduga la referine proiectul 1, ar iei "Referin Circular".

Editarea coloanelor: n acest moment, toate proprietile publice ale clasei "Student" (inclusiv cele
motenite de la clasa printe "Person") vor fi ataate sub form de coloane la grid. Dar nu toate
aceste coloane sunt utile, limitm aceste coloane la strictul necesar.

Se selecteaz link-ul "Edit Columns" din proprietile gridului i se intr n fereastra de editare a coloanelor.
Aici avem posibilitatea s definim pentru fiecare coloan modul de afiare, textul de header, sau eventual
s adugm coloane noi, diferite de cele din clasa Student (de exemplu, vom aduga coloane ce conin
butoane pentru tergerea studentului din baza de date, modificarea lui, sau adugarea unui student nou).

Vom lsa doar coloanele utile i se adaug coloanele de tip "DataGridViewLinkColumn": Del, Update i
Add.

Version no.: 2

Page 74 of 83

Observaie: proprietile PKStudClass i PKStud trebuie adugate n clasa "Student". Ele vor conine PKurile din tabelele "grupe_studenti" i "studenti" din baza de date pentru studentul respectiv.

Afiarea datelor: n cadrul constructorului formei se apeleaz funcia "FillCbYear()". Mergnd n


cascad pe evenimentele "SelectedIndexChanged" se vor popula toate controalele cu datele
specifice anului universitar curent. Ultimul eveniment se produce la ComboBox-ul "cbClass" ce va
apela funcia de populare a gridului "FillDgStudent()":

Se preiau anul universitar i grupa selectate n ComboBox-uri i se determin lista studenilor nscrii n
acea grup pentru acel an (List<Student> studList = DS_Student.GetStudentList(pkClass,
pkYear)) . Funcia este implementat n clasa DS_Student i este similar cu celelalte funcii de tip "Get..".
Diferenele ntre aceste funcii sunt date de fraza SQL ce trebuie executat:

Lista de studeni obinut se ataeaz ca DataSource la gridul de afiare.


In sfrit, avem o form funcional, ce afieaz studenii filtrai dup grupe i ani universitari:

Version no.: 2

Page 75 of 83

5.3.5 Interceptarea evenimentelor date de grid


Dac facem click pe unul din butoanele din grid n acest moment, nu se ntmpl nimic. Deoarece nu am
ataat nici o funcie la evenimetele trimise de grid. Sunt multe moduri de a rezolva aceast problem, dar
cel mai simplu ar fi s interceptm evenimentul "CellClick" al gridului i pe acel eveniment s rezolvm
toate butoanele.
Evenimentul "CellClick" apare la orice click al utilizatorului ntr-o celul de grid, deci inclusiv n celulele
cu nume, prenume, etc. Sunt dou filtrri ce trebuie realizate pe acest eveniment:
- Eliminarea click-urilor pe alte celule dect cele cu butoane:
dgStudent.CurrentCell.GetType() != typeof(DataGridViewLinkCell)
- Identificarea butonului pe care s-a facut click:
if ((string)dgStudent.CurrentCell.Value == "Update")

Version no.: 2

Page 76 of 83

Butoanele "Update" i "Add" sunt tratate aproximativ la fel, ambele deschid forma "StudentView", dar n
moduri diferite. Butonul de adugare deschide forma n starea ei normal (forma a fost fcut tocmai pentru
a aduga studeni n baza de date), pe cnd butonul de "Update" trebuie s deschid forma care s afieze
datele studentului selectat. In acest mod, utilizatorul doar modific anumite date, dup care studentul
trebuie updatat n baza de date.
Pentru modul de "Update" s-a implementat un nou constructor al clasei "StudentView" ce primete ca
parametru ntregul "pkStudClass" , adic valoarea "pk_student_grupa" din baza de date. Aceast valoare
identific n mod unic linia din tabela "studenti_grupe" ce identific la rndul ei n mod unic studentul
(pk_student), grupa (pk_grupa) i anul universitar (pk_an_universitar).
Trebuie adugat n fiecare clas (DS_Student, DS_Class, DS_Year) cte o funcie ce primete parametrul
pk_student_grupa i returneaz n mod unic studentul, grup i anul. Prezent n continuare numai funcia
din clasa DS_Class, celelalte se construiesc n mod asemntor:

Version no.: 2

Page 77 of 83

Noul constructor al formei "StudentView" apeleaz vechiul constructor pentru iniializarea controalelor, apoi
seteaz anumite controale n funcie de studentul primit ca parametru ( ComboBoxul cu grupele trebuie s
fie setat pe grupa studentului, butonul "Salvare in baza de date" se transform n "Update", etc):

Mai sunt necesare cteva modificri pentru a face forma funcional, noi doar evideniem dou funcii ce
trebuie modificate: "bSaveDB_Click":

Version no.: 2

Page 78 of 83

, respectiv "DS_Student.UpdateStudent(currStudent)":

5.3.6 Inscrierea studenilor n grupe


La nceputul fiecrui an universitar studenii ce s-au nscris la facultate n primul an trebuie repartizai pe
grupele din anul unu, respectiv studenii mai vechi care au absolvit un an de studiu trebuie nscrii n
urmtorul an de studiu.
Vom face o form special pentru n scrierea studenilor n diverse grupe i pentru diveri ani de studiu.
Forma este similara cu cea precedent, cu deoasebirea c gridul conine un singur buton "Inscrie" care va
avea ca efect nscrierea studentului din linia curent n grupa i anul de studiu selectat.

Version no.: 2

Page 79 of 83

Inserm un buton ajuttor "Vezi numai studentii fara grupa" ce va afia numai studenii care nu sunt nscrii
n anul universitar curent.
Este foarte important s nu nscriem de dou ori un student n acelai an universitar. Cea mai sigur soluie
este s adugm o constrngere de tip "unique" pe tabela "studenti_grupe" pentru perechea de coloane
"pk_student" i "pk_an_universitar":
alter table studenti_grupe add constraint u_student_an unique(pk_student,
pk_an_universitar);
Bineneles, toate aceste modificri necesit adugarea de cod nou n proiectele noastre, dar toate aceste
modificri pot fi realizate pe baza template-ului prezentat pn n acest moment. Ne rezumm s
exemplificm funcia de nscriere student din proiectul "DataSource":

Version no.: 2

Page 80 of 83

5.3.7 Conectarea aplicaiei la diverse tipuri de baze de


date
Toate funciile din proiectul "DataStore" sunt specifice bazei de date Microsoft SqlExpress. Stringul de
conectare la baz utilizeaz drivere native ale bazei de date pentru accesarea informaiei. De aceea i
obiectele folosite pentru accesarea bazei erau specifice serverului SqlExpress: SqlConnection,
SqlCommand.
Dar dac vrem s ne conectm la alt baz de date (Oracle, Acces, MySql, SQLite, etc), atunci aceste
obiecte nu mai sunt valabile. Oracle pune la dispoziie drivere proprii n biblioteca "using
Oracle.DataAccess.Client"
n
care
definete
obiecte
proprii
(OracleConnection,
OracleCommand).
Totui, exist un mod unic de accesa diverse baze de date folosind aceleai obiecte. Aceast tehnologie se
numete ODBC (Open Database Connectivity) i are scopul de accesa diversa baze de date n mod similar,
independent de baza de date sau de sistemul de operare. In acest caz se lucreaz cu obiectele
OdbcConnection, OdbcCommand ce au aceeai funcionalitate ca cele similare din SqlExpress.
In figura de mai jos sunt date diverse stringuri de conectare la diverse baze de date folosind tehnologii
diferite:

Se observ c pot s pot s m conectez la aceeai baz de date SqlExpress, dar folosind de data aceasta
ODBC. La fel de bine, m conectez la baza Oracle folosind tot ODBC. Avantajul utilizrii ODBC este c pot
interschimba bazele de date fr s modific codul de program, ci doar stringul de conectare, n rest
obiectele rmn aceleai.
Nu mai creez aceste obiecte n fiecare clas, ci fac o singur clas "DataBaseTools" care va returna
obiectul "OdbcCommand" ce este conectat la o baz de date specific:

Version no.: 2

Page 81 of 83

Am folosit directiva preprocesor "#define odbc", iar n funcie de aceasta, funcia "GetSqlCommand"
returneaz un obiect de tip SqlCommand, sau OdbcCommand. Funciile din clasele DS_Class,
DS_Student, DS_Year nu vor mai crea obiectul SqlCommand, ci-l vor cere de la clasa "DataBaseTools". Nu
se specific tipul obiectului folosit pentru c el se poate modifica n funcie de directiva #define, de aceea se
folosete construcia: "var cmd = DataBaseTools.GetSqlCommand();" .
Totui exist o diferen ntre obiectele SqlCommand i OdbcCommand: OdbcCommand nu accept
parametri n sintaxa "@nume_parametru" ci doar semnul "?", iar parametrii trebuie adugai strict n ordinea
utilizrii lor n fraza SQL. De aceea, am anulat capitolul "Parameters", punnd direct n string valorile
acestor parametri:

Recapitulare: n acest capitol s-a construit o form simpl pentru vizualizarea studenilor, cu posibilitatea
modificrii datelor specifice fiecrui student. S-au introdus cteva concepte noi dintre care amintim:
Utilizarea obiectelor de tip "DataGridView" pentru afiarea datelor tabelare.
Inserarea de butoane n coloanele gridului pentru efectuarea anumitor sarcini.
Crearea dinamic a unei forme i lansarea ei n execuie.
Prezentarea tehnologiei ODBC pentru conectarea uniform la diverse baze de date.

Version no.: 2

Page 82 of 83

6 Bibliografie
http://www.c-sharpcorner.com
http://msdn.microsoft.com/en-us/library/67ef8sbd(v=vs.80).aspx
http://csharp.net-informations.com/
http://www.csharp-station.com/Tutorial.aspx

Version no.: 2

Page 83 of 83

S-ar putea să vă placă și