Documente Academic
Documente Profesional
Documente Cultură
Version no.: 2
Page 1 of 83
Cuprins
1
INTRODUCERE......................................................................................................................................................4
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
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
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
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
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!
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
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.
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
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.
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.
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":
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.
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.
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.
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.
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.
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
Version no.: 2
Page 17 of 83
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.
Version no.: 2
Page 18 of 83
2.4.2 Incapsulare
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.
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:
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
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
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)
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:
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.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
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
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
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".
Dac se incearc apelul unei metode din obiectul declarat , dar neinstaniat:
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
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.1
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
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
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.
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
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
Version no.: 2
Page 33 of 83
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).
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:
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);
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
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
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.
Version no.: 2
Page 40 of 83
Din acest moment, toate clasele publice definite n acest proiect vor fi accesibile n
proiectul "Hello".
Version no.: 2
Page 41 of 83
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:
Version no.: 2
Page 42 of 83
Version no.: 2
Page 43 of 83
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
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.
Version no.: 2
Page 45 of 83
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.
Version no.: 2
Page 46 of 83
S-a utilizat metoda tbMedie.Focus() pentru a aduce mouse-ul n cmpul tbMedie semnaliznd astfel
utilizatorului care este cmpul cu informaia greit.
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
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.
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
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
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();
}
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).
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... :
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:
Version no.: 2
Page 55 of 83
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:
Version no.: 2
Page 58 of 83
Version no.: 2
Page 59 of 83
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".
Click dreapta pe folderul "Tables" din baza Student i se alege opiunea "New Table":
Version no.: 2
Page 60 of 83
o
o
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
o
In final, diagrama bazei de date "Student" ar trebui s arate conform figurii de mai jos:
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)
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
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
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.
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.
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.
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:
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
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):
Version no.: 2
Page 71 of 83
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:
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
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.
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:
Version no.: 2
Page 75 of 83
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)":
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
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