Sunteți pe pagina 1din 30

Interfee Windows n C#

Scurt istoric
C# (pronunai C sharp - in traducere literal C diez) este un limbaj de
programare orientat pe obiecte asemntor limbajului C++. El a fost dezvoltat de firma
Microsoft, ca soluie standard pentru dezvoltarea aplicaiilor Windows. Creatorii lui sunt
Anders Hejlsberg (autor al limbajelor Turbo Pascal i Delphi), Scot Wiltamuth i Peter
Golde.
C#

respect

standardul

ECMA-334

(European

Computer

Manufactures

Association).
Limbajul C# folosete Microsoft .NET Framework, o colecie de clase care poate
fi descrcat prin Internet i care este ntreinut i ameliorat permanent de Microsoft.
Prima versiune dateaz din 2001, deci toat aceast soluie tehnologic este de dat
recent.
Clasele coninute n .NET sunt neutre fa de limbaj (aplicaiile pot fi scrise n
diverse limbaje) i uureaz munca de programare n realizarea interfeelor aplicaiilor,
accesul la date, conectarea la servere de baze de date, accesarea resurselor din
Internet, programarea aplicaiilor bazate pe comunicaii prin reele, etc..
Aplicaiile care folosesc .NET sunt executate ntr-un mediu software denumit
CLR (Common Language Runtime).

Acesta poate fi asimilat unui procesor virtual,

asemntor mainii virtuale Java, care furnizeaz servicii de management a resurselor


calculatorului, asigurare a stabilitii i securitii execuiei. Dei Microsoft a conceput
CLR ca soluie destinat propriilor sisteme de operare, la ora actual exist astfel de
procesoare virtuale i pentru alte sisteme de operare. Astfel, n cadrul proiectului Mono
- www.gomono.com, susinut de compania Novell, s-au dezvoltat soluii alternative
pentru Linux, Solaris, Mac OS, BSD, HP-UX, i chiar Windows, asigurndu-se astfel
portabilitatea aplicaiilor scrise n limbaje bazate pe .NET.

Tratarea programelor scrise n C#


Un program scris n C# este supus unei prime compilri n urma creia se obine
un cod scris ntr-un limbaj intermediar (CIL - Common Intermediate Language).

aceast form aplicaia este apoi trimis procesorului virtual (CLR) care realizeaz
traducerea n cod main i execut aplicaia.

Compilare

Limbaj intermediar
(Common Intermediate
Language - CIL)

Compilare CIL - cod


main i executare

Realizarea unei aplicaii elementare n C#


Dezvoltarea de aplicaii n C# se realizeaz folosind un mediu de programare,
firma Microsoft oferind mediul profesional Visual C# .NET. O soluie alternativ gratuit
poate

fi

versiunea

Express

Edition

mediului

profesional

(http://www.microsoft.com/express/vcsharp/), utilizabil pentru nvarea limbajului i


pentru realizarea interfeelor aplicaiilor Windows.

Microsoft ofer ns i varianta

realizrii aplicaiilor folosind pachetul gratuit .NET Framework Software Development Kit
(SDK).

De altfel simpla descrcare a pachetului de baz .NET Framework pus la

dispoziie de Microsoft adaug n directorul C:\Windows\Microsoft.NET\Framework\vxx\

(xx este versiunea descrcat) compilatorul csc.exe utilizabil n mod linie de comand i
care produce cod executabil.
Exemplu de aplicaie tip consol:
class Salut
{
public static void Main()
{
System.Console.WriteLine("Salut, prieteni!");
}
}

Aplicaia tip consol va fi salvat ntr-un fiier denumit Salut.cs i apoi va fi


compilat folosind csc.exe:
>csc Salut.cs
n urma compilrii va rezulta fiierul Salut.exe care poate fi executat din linia de
comand:

Observaie:
Pentru a folosi compilatorul csc.exe fr a preciza calea este necesar
modificarea variabilei de mediu Path. Pentru aceasta se va accesa Control Panel /
System / Advanced. n fereastra care se afieaz se va selecta Environment Variables
iar n fereastra Environment Variables va fi editat variabila Path adugnd cilor deja
existente calea spre directorul care conine compilatorul csc.exe.

Pentru .NET

versiunea 3.5, cea mai recent n momentul scrierii acestui curs, calea este:
C:\WINDOWS\Microsoft.NET\Framework\v3.5.

Noiuni de C#
Spaii de nume
Spaiul de nume reprezint un concept aprut n C++ odat cu extinderea
programrii obiectuale. Clasele care alctuiesc o aplicaie pot proveni din surse diferite
i pot avea din ntmplare aceeai denumire. Dac programatorii au creat clasele n
spaii de nume distincte, eventualele coincidene de nume pot fi uor rezovate,
denumirea fiecrei clase fiind precedat de denumirea spaiului de nume cruia i
aparine.
Pentru a evita tastarea spaiului de nume naintea fiecrei denumiri de clas n
C# se folosete ca i n C++ clauza using.
.NET Framework definete peste 90 de spaii de nume, majoritatea avnd
denumiri ncepnd cu System. n exemplele coninute n cursurile urmtoare vor fi
frecvent folosite spaiile de nume System, System.Windows.Form i System.Drawing.
Exemplul de aplicaie prezentat poate fi rescris folosind clauza using, clasa
Console aparinnd spaiului de nume System.

using System;
class Salut
{
public static void Main()
{
Console.WriteLine("Salut, prieteni!");
}
}

Comentarii
Programele scrise n C# pot conine explicaii sub forma unor comentarii.
Acestea vor asigura n timp nelegerea diferitelor metode i rolul funcional al
variabilelor folosite.
Ca i n C++, n n C# pot fi folosite dou tipuri de comentarii:
comentarii "n linie", introduse prin //. Un astfel de comentariu se ncheie la
sfritul liniei curente;
comentarii pe unul sau mai multe rnduri consecutive. Zona care conine
comentariul este delimitat prin /*

(comentariu) */.

De regul se folosesc comentariile n linie, cel de-al doilea tip fiind folosit frecvent
n timpul depanrii programelor mari i complexe, pentru a suprima din program
anumite zone.

Tipuri de date
n mare C# folosete tipurile de date simple existente i n C++. Fiecare dintre
tipurile simple este ns dublat de o clas din spaiul de nume System. Rolul acelei
clase este puin evident n acest moment. n cele ce urmeaz va fi inclus un exemplu n
care vor fi referite proprieti ale tipurilor simple n acelai mod n care sunt referite
proprieti ale claselor. De exemplu int.MaxValue, furnizeaz valoarea ntreag cea mai
mare care poate fi pstrat ntr-o variabil de tip int. Tot dublarea tipurilor simple prin
clase va face posibil folosirea unor variabile aparinnd unor tipuri simple n situaii n
care sunt acceptate doar obiecte.

a. Tipuri de date ntregi:


Numr de bii

Tip simplu

Clas

Semn

sbyte

System.SByte

cu semn

byte

System.Byte

fr semn

16

short

System.Int16

cu semn

16

ushort

System.UInt16

fr semn

32

int

System.Int32

cu semn

32

uint

System.UInt32

fr semn

64

long

System.Int64

cu semn

64

ulong

System.UInt64

fr semn

Exemple de declaraii:
int a = 12, b, contor; // Se putea scrie i System.Int32 a = 12, b, contor;
b. Tipuri de date reprezentate n virgul mobil
Numr de bii

Tip simplu

Clas

32

float

System.Single

64

double

System.Double

c. Tipul decimal
Limbajul C# admite pe lng tipurile de date numerice menionate un tip nou,
decimal.

Pentru decimal lungimea de reprezentare este de 128 bii iar clasa

corespunztoare din spaiul de nume System este System.Decimal.


d. Tipul bool
C# admite declararea de variabile logice, ale cror valori posibile sunt true i
false.

Pentru declararea unei astfel de variabile se folosete bool, clasa

corespunztoare din spaiul de nume System fiind System.Boolean.


Operatorii relalionali (==, !=, <, <=, >, >=) genereaz o valoare de tip bool.
e. Tipul char

Tipul char permite declararea unei variabile care va conine un caracter n format
Unicode (pe 16 poziii binare). Clasa corespunztoare din spaiul de nume System este
System.Char.
f. tipul string
O simplificare semnificativ pe care o aduce C# n raport cu C++ este
introducerea tipului string pentru declararea variabilelor care conin iruri de caractere.
Clasa corespunztoare din spaiul de nume System este System.String.
Exemple:
string a = "X = "; // Se putea i System.String a = "X = ";
double p = 129.2;
int nr = a.Length; // .Length furnizeaz lungimea irului a.
string b = a + p + "mm";

n C# operatorul '+' indic fie operaia de adunare fie cea de concatenare (unire)
a dou iruri de caractere. Pentru toate tipurile de date menionate (mai exact pentru
toate tipurile derivate din clasa Object, rdcina ierarhiei de clase destinate pstrrii
datelor) este definit metoda ToString() care returneaz o reprezentare sub form de ir
de caractere a valorii variabilei pentru care este apelat.

Expresia care definete

valoarea variabilei b ncepnd cu a, un string, variabila real p este automat convertit


n ir de caractere chiar dac nu este apelat n mod explicit metoda ToString(). O
soluie mai clar ar fi fost ns:
string b = a + p.ToString() + "mm";

g. Variabile de tip tablou


O variabil de tip tablou se declar adugnd o pereche de paranteze drepte ([ ])
dup cuvntul rezervat care definete tipul valorilor coninute. Exemplu:
int [ ] tab;

Dup declarare valoarea variabilei tab este null. Variabila va primi o valoare
diferit de null n momentul rezervrii unei zone de memorie pentru pstrarea
elementelor tabloului, folosind operatorul new:
tab = new int[12];

De obicei declararea se combin cu alocarea de memorie, scriindu-se:


int [ ] tab = new int[12];

sau, dac se realizeaz concomitent i atribuirea de valori:


int tab [ ] = new int[4] {1, 4, -2, 5}; // sau chiar mai simplu: int tab [ ] = {1, 4, -2, 5};

Ulterior se poate folosi variabila tab pentru un alt ir de valori int, astfel:
tab = new int[5];

n acest caz, dei nu s-a realizat o eliberare explicit a memoriei (n C# nu exist


operatorul delete), blocul de memorie alocat iniial va fi n mod automat eliberat i repus
la dispoziia aplicaiei.

Procesul de identificare a blocurilor de memorie devenite

disponibile face obiectul activitii unei componente a CLR denumit garbage collector
(colector de reziduuri).
Exemplu: S se scrie o aplicaie tip consol care afieaz valorile numerice
maxime i minime care pot fi memorate folosind diferite tipuri de variabile.
using System;
class Dimens
{
public static void Main()
{
Console.WriteLine("Sbyte: {0} la {1}",sbyte.MinValue, sbyte.MaxValue);
Console.WriteLine("byte: {0} la {1}",byte.MinValue, byte.MaxValue);
Console.WriteLine("Short: {0} la {1}",short.MinValue, short.MaxValue);
Console.WriteLine("uShort: {0} la {1}",ushort.MinValue, ushort.MaxValue);
Console.WriteLine("int: {0} la {1}",int.MinValue, int.MaxValue);
Console.WriteLine("uint: {0} la {1}",uint.MinValue, uint.MaxValue);
Console.WriteLine("long: {0} la {1}",long.MinValue, long.MaxValue);
Console.WriteLine("ulong: {0} la {1}",ulong.MinValue, ulong.MaxValue);
Console.WriteLine("float: {0} la {1}",float.MinValue, float.MaxValue);
Console.WriteLine("double: {0} la {1}",double.MinValue, double.MaxValue);
}
}

Operatorii limbajului C#
n definirea unui limbaj, stabilirea operatorilor care pot fi folosii la scrierea
expresiilor i a regulilor lor de utilizare reprezint o etap important. Limbajele de nivel
nalt folosesc un mare numr de operatori i chiar permit extinderea setului de operatori
pentru a putea scrie expresii n care intervin variabile aparinnd tipurilor structurate
(obiecte).
Operatorii matematici din C#
+

% (modulo)

x % y furnizeaz restul mpririi ntregi a lui x la y.


Exemplu de utilizare a operatorului '%':
if((an % 4 == 0 && an % 100 !=0) || an % 400 == 0)
System.Console.WriteLine(an + " este bisect.");

Operatorul % se aplic doar tipurilor ntregi.


Operatorul "/" poate provoca trunchiere n cazul operanzilor ntregi.
Evaluarea expresiilor aritmetice se efectueaz de la stnga la dreapta
respectnd ordinea de evaluare normal.
Operatorii de comparare i logici
Operatorii de comparare (relaionali) din C# sunt : > >= < <= == !=
Operatorii de comparare au o prioritate inferioar celor aritmetici :
i < lim + 1 se evalueaz ca i

i < (lim + 1)

O expresiile n care intervine o succesiune de operatori logici && (i) sau o


succesiune de operatori || (sau) sunt evaluate de la stnga la dreapta i evaluarea
expresiei nceteaz cnd se tie deja valoarea de adevr a rezultatului.
&& e mai prioritar ca i || iar ambele sunt mai puin prioritare ca i operatorii de
comparaie.
Operatorul ! (negaie)
if (!corect) . . .

identic cu if (corect == false) . . .

n C# termenii pentru care sunt folosii operatorii && i || sunt obligatoriu de


tip bool. n C# nu opereaz regula din C conform creia o valoare numeric diferit
de 0 are valoarea de adevr true i o valoare 0 are valoarea de adevr false.
Conversiile de tip
Limbajul C# este mult mai riguros n ceea ce privete corespondena tipurilor
termenilor dintr-o expresie. Frecvent utilizarea ntr-o expresie a unor operanzi de tipuri
diferite este semnalat ca eroare. Eliminarea erorilor se va face fie folosind operatorii
de tanstipaj (ca n C) fie apelnd metode din clasa Convert.
Operatorii de conversie de tip (transtipaj sau cast)
(nume-tip) expresie
expresie este convertit n tipul specificat :
x = Math.Sqrt((double)n)
alfa = (float)a / j ;

Conversia explicit folosind metodele clasei Convert permite trecerea unei


variabile sau a unei expresii dintr-un tip n altul. Exemplu:
int z = Convert.ToInt32(312.14);

Practic dac este necesar o conversie se va folosi facilitatea mediului de


programare de a afia pemanent posibilitile de continuare a scrierii i se va selecta
varianta dorit.

Operatorii de incrementare i de decrementare ++ i -n funcie de poziia operatorului fa de variabila incrementat, se realizeaz pre
i post incrementare (decrementare)

int n = 5 ;
x = n++ ;
atribuie 5 lui x

x = ++n ;
atribuie 6 lui x

Operatorii i expresiile de atribuire


Expresia :
i = i + 3;

n care variabila din stnga egalului se repet n dreapta acestuia se mai poate scrie
astfel :
i += 3 ;

Instruciunile limbajului C#

Instruciunea de decidere - if
Ca i n C, ansamblul de instruciuni cuprinse ntre acolade formeaz o
instruciune compus sau un bloc de instruciuni. Instruciunile din interiorul unui bloc
de instruciuni sunt executate n ordinea n care sunt scrise.
Variante de scriere a instruciunii if
if ( expLogica )
instruciune;

if (expLogica )
{
mai multe instruciuni
}

if (expLogica )
instruciune;
else
instruciune;

if (expLogica )
{
mai multe instruciuni
}
else
{
mai multe instruciuni
}

if (expLogica )
instruciune;
else
{
mai multe instruciuni
}

if (expLogica )
{
mai multe instruciuni
}
else
instruciune;

Indentarea instruciunilor sau a blocurilor de instruciuni (scrierea decalat)


din if nu este obligatorie dar are mare importan n nelegerea i depanarea
programului.

Instruciunea while
Instruciunea while permite realizarea unei structuri repetitive (ciclu) condiionate
anterior. Corpul ciclului poate fi executat o dat, de mai multe ori sau de loc.
Exemplu fundamental:
int contor = 1;
while ( contor <= 3 )
{
Console.WriteLine("Contor = "+contor);
contor = contor + 1; // sau mai bine contor++
}
Console.WriteLine("La revedere!");

Sintaxa instruciunii while este:


while ( condiie )
instruciune

Condiia este o expresie logic (evaluat la o valoare de tip bool).

Sintaxa instruciunii while


while ( condiie )
instruciune;

while ( condiie )
{
una sau m. m.instruciuni
}

Instruciunea do

Pentru programarea unui ciclu poate fi folosit ntotdeauna instruciunea while.


Deoarece while ncepe prin executarea unui test, n cazul n care variabila testat nu

poate primi valori dect n interiorul ciclului, programatorul trebuie s-i dea la nceput o
valoare convenabil pentru a determina intrarea n ciclu. Exacutarea instruciunilor din
corpul ciclului va corecta automat valoarea iniial.
Pentru astfel de cazuri exist ns i o cale mai simpl, respectiv folosirea
instruciunii do.
Exemplu:
g = 9.81;
t = 0;
do
{
d = (g * t * t ) / 2;
Console.WriteLine( t + " " + d);
t = t + 1;
}
while (d <= 500);

Instruciunea for
Instruciunea for este preferat ori de cte ori trebuie realizat un ciclu care
folosete un contor.
Dac naintea unui ciclu trebuie realizate mai multe iniializri, acestea pot scrise
n for una dup alta, desprite prin virgule:
class Program
{
public static void Main(String[] args)
{
int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i, sum;
for (i = 0, sum = 0; i < a.Length; i++)
sum = sum + a[i];
Console.WriteLine("Suma elementelor sirului a este: " + sum);
}
}

Oricare dintre cele trei pri ale instruciunii for pot lipsi. Lipsa condiiei de reluare
este echivalent cu a scrie o condiie care este ntotdeauna adevrat. Ieirea dintr-un
astfel de ciclu se poate face folosind instruciunea break.
Exemplu:
for ( ; ; )

{
..
break;
..
}

Executarea instruciunii break provoac o ieire imediat din ciclul for. Ea poate
fi folosit i pentru a iei din ciclurile while sau do.

Instruciunea foreach
Instruciunea foreach a fost preluat n C# din Visual Basic.

Ea permite

parcurgerea sistematic a elementelor unui ir sau a unei liste, realizabil n C# folosind


una dintre clasele din spaiul de nume System.Collection.
Exemple:
int sir = new int[12];
foreach (int i in sir)
i = 10;
...
foreach (int i in sir)
Console.Write("{0} ", i);

n exemplu, primul foreach pune 10 n toate elementele din irul de valori ir iar al
doilea afieaz valorile sdin ir pe o linie.

Instruciunea switch
Instruciunile de ciclare prezentate, sunt folosite pentru realizarea blocurilor de
instruciuni a cror execuie ncepe cu prima linie i este controlat de ctre
programator.

Instruciunea switch este folosit tot pentru a construi un bloc de

instruciuni dar punctul de unde ncepe execuia depinde de valoarea unei expresii
avnd valori ntregi.
Sintaxa instruciunii este:
switch (expresie)
{
case constanta_1 : instruciuni
case constanta_2 : instruciuni

...
default : instruciuni;
}
Fiecare dintre punctele de unde poate ncepe execuia blocului este etichetat
printr-o constant avnd valoare ntreag. Dac expresia de testat corespunde uneia
dintre constante, execuia blocului ncepe din punctul indicat de aceasta.
Cazul default este facultativ.
Exemplu :
switch (t)
{
case 's':
rez = Math.Sin(Math.PI * x / 180.0);
Console.WriteLine("rezultatul este : " + rez);
break;
case 'c':
rez = Math.Cos(Math.PI * x / 180.0);
Console.WriteLine("rezultatul este : " + rez);
break;
case 't':
rez = Math.Sin(Math.PI * x / 180.0) / Math.Cos(3.14159 * x / 180.0);
Console.WriteLine("rezultatul este : " + rez);
break;
default:
Console.WriteLine("Caracter incorect!");
break;
}

Ca i n cazul ciclurilor, instruciunea break provoac o ieire imediat din blocul


realizat folosind switch.
Observaie: n C# break apare i n secvena introdus prin clauza default.

Programare obiectual n C#
Limbajul C# permite scrierea de aplicaii folosind exclusiv programarea
obiectual. O aplicaie scris n C# este alctuit dintr-un ansamblu de clase, una
dintre ele fiind clasa principal deoarece conine metoda Main(), punctul de intrare n
aplicaie.
Exemplu fundamental:

Se consider o aplicaie care afieaz a cta zi din an este o zi dat prin


definirea anului, lunii i a zilei din lun.
Pentru rezolvarea problemei s-a creat clasa DCalend:
class DCalend
{
private int anul;
private int luna;
private int ziua;
public DCalend(int aa, int ll, int zz)
{
anul = aa;
luna = ll;
ziua = zz;
}
public bool AnBisect()
{
return (anul % 4 == 0) && ((anul % 100 != 0) || (anul % 400 == 0));
}
public int ZiuaDinAn()
{
int[] luniz = new int[] { 0,31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
return luniz[luna - 1] + ziua + (luna > 2 && AnBisect() ? 1 : 0);
}
}

Ca i n C++, n C# o clas conine n principal un numr de membri date sau


cmpuri (anul, luna, ziua) i un numr de metode (funcii) care opereaz asupra
membrilor date. Metodele clasei DCalend sunt:

DCalend(), o metod care poart numele clasei i iniializeaz membrii


date ai acesteia.

n programarea obiectual o astfel de metod se

numete constructor;

AnBisect(), care returneaz o valoare bool care indic dac anul este an
bisect i

ZiuaDinAn() care calculeaz a cta zi din an este ziua definit prin valorile
curente din cmpurile clasei.

Spre deosebire de C++ n clasele C# metodele sunt scrise integral.


Folosind clasa DCalend s-a scris urmtoarea aplicaie tip consol:
using System;
namespace POB01

{
class Program
{
public static void Main(String[] args)
{
DCalend data = new DCalend(2007, 8, 29);
Console.WriteLine("Ziua din an = {0}", data.ZiuaDinAn());
}
}
class DCalend
{
private int anul;
private int luna;
private int ziua;
public DCalend(int aa, int ll, int zz)
{
anul = aa;
luna = ll;
ziua = zz;
}
public bool AnBisect()
{
return (anul % 4 == 0) && ((anul % 100 != 0) || (anul % 400 ==
0));
}
public int ZiuaDinAn()
{
int[] luniz = new int[] { 0,31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
return luniz[luna - 1] + ziua + (luna > 2 && AnBisect() ? 1 : 0);
}
}
}

Pe lng clasa DCalend aplicaia mai are clasa Program care conine doar
metoda principal Main(). n metoda principal se declar i se iniializeaz (prin apelul
constructorilui) obiectul data i apoi se afieaz pe ecran a cta zi din an este data.
Pentru apelul metodelor clasei DCalend se scrie:

data.ZiuaDinAn() dac metoda este apelat dintr-o alt clas, respectiv

AnBisect() dac metoda este apelat dintr-o alt metod a aceleiai clase.

n programarea obiectual se definete i o a treia variant de apel a unei


metode, nume_clas.metod. Un exemplu este apelul deja utilizat, Math.Sin(...). Math
este o clas din spaiul de nume System care conine definiiilor funciilor matematice
implementate n C#.

O funcie astfel apelat opereaz asupra argumentelor sale,

pentru apelul ei nefiind necesar definirea n prealabil a unui obiect aparinnd aceleiai

clase. Pentru a declara o astfel de funcie, n programarea obiectual se folosete


cuvntul rezervat static. n ecemplul dat metoda AnBisect() putea fi declarat static.
Avantajul ar fi fost acela de a o putea folosi n orice aplicaie, fr a fi necesar
cunoaterea clasei DCalend i fr a defini un obiect din clasa DCalend.
Cmpurile pot fi i ele definite ca fiind statice. O astfel de soluie este indicat n
cazul cmpurilor care au aceleai valori pentru toate instanele clasei. n exemplul dat,
irul de valori ntregi luniz este constant, deci poate fi declarat static.
Clasa DCalend ar fi atunci definit astfel:
class DCalend
{
private int anul;
private int luna;
private int ziua;
static int[] luniz = new int[] { 0,31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
public DCalend(int aa, int ll, int zz)
{
anul = aa;
luna = ll;
ziua = zz;
}
public static bool AnBisect(int anul)
{
return (anul % 4 == 0) && ((anul % 100 != 0) || (anul % 400 == 0));
}
public int ZiuaDinAn()
{
return luniz[luna - 1] + ziua + (luna > 2 && AnBisect(anul) ? 1 : 0);
}
}

Proprieti
Ca i n orice alt limbaj care permite programarea obiectual, n C# o clas are
membri date denumii i cmpuri i membrii coninnd cod denumii metode. Clasele
C# mai pot conine i ali membrii coninnd cod denumii proprieti, extrem de
importani n .NET Framework.
Originea problemei rezolvate prin introducerea proprietilor este urmtoarea:

n POO membrii date sunt de regul declarai privai (private). Accesul la un


astfel de cmp dinafara clasei care l conine este atunci rezolvat prin adugarea unei
perechi de metode:

metod

pentru

modificarea

valorii,

denumit

de

obicei

setnume_camp(tip val_noua) i

o metod pentru preluarea valorii, denumit de obicei getnume_camp().

O astfel de soluie este destul de greoaie i mrete considerabil numrul de


metode ale claselor care trebuie scrise. De exemplu mediul de programare Netbeans
destinat scrierii de aplicaii n Java ofer ca facilitate dezvoltatorilor scrierea automat a
perechii de funcii de acces set - get.
n C#, prin introducerea proprietilor se ncearc o simplificare accesului la
cmpurile private.
Exemplu:
Se consider cmpul anul din clasa DCalend prezentat deja. Se poate aduga
clasei DCalend secvena urmtoare de cod care definete proprietatea Anul:
public int Anul
{
set
{
anul = value;
}
get
{
return anul;
}
}

Se observ c proprietatea definit are acelai nume cu cmpul privat pe care l


acceseaz, cu diferena c ncepe cu o majuscul.

De altfel programatorii n C#

denumesc n mod sistematic membrii publici ai claselor cu denumiri care ncep cu o


majuscul. De asemenea se vede c definirea unei proprieti nseamn tratarea n
dou secvene de cod a impunereii valorii cmpului (set : cmp = value) i a prelurii
acesteia (get : return cmp). Evident secvena de cod introdus prin set poate testa
valabilitatea valorii value.
Exemplu de utilizare a proprietii n funcia Main():
public static void Main(String[] args)
{

DCalend data = new DCalend(2007, 8, 29);


Console.WriteLine("Ziua din an = {0}", data.ZiuaDinAn());
data.Anul = 2006;
Console.WriteLine("Ziua din an = {0}", data.ZiuaDinAn());
}

Parametrii metodelor
n C# parametrii metodelor sunt ntodeauna transferai prin valoare. Ca i n C,
n acest caz modificrile operate n cadrul metodei asupra valorilor parametrilor formali
ai acesteia nu schimb valorile variabilelor corespunztoare din metoda apelant.
Exemplu:
using System;
namespace Test
{
class Invers
{
public static void Main(string[] args)
{
Invers z = new Invers();
z.Calcule();
}
public void Calcule()
{
int a=10, b=2;
Console.WriteLine("Valori initiale: a = {0}, b = {1}", a, b);
Inv(a, b);
Console.WriteLine("Dupa apel: a = {0}, b = {1}", a, b);
}
public void Inv(int x, int y)
{
int aux;
aux = x;
x = y;
y = aux;
}
}
}

Metoda Inv() din exemplul dat este eronat deoarece transmiterea prin valoare a
parametrilor face ca inversarea realizat s nu afecteze variabilele din metoda apelant
(a i b).

Pentru a impune ca transmiterea parametrilor s nu se realizeze prin valoare ci


prin referin, n C# se folosete clauza ref. Aplicaia din exemplul precedent ar fi trebuit
scris atunci astfel:
using System;
namespace Test
{
class Invers
{
public static void Main(string[] args)
{
Invers z = new Invers();
z.Calcule();
}
public void Calcule()
{
int a=10, b=2;
Console.WriteLine("Valori initiale: a = {0}, b = {1}", a, b);
Inv(ref a, ref b);
Console.WriteLine("Dupa apel: a = {0}, b = {1}", a, b);
}
public void Inv(ref int x, ref int y)
{
int aux;
aux = x;
x = y;
y = aux;
}
}
}

Motenirea
Toate limbajele destinate programrii obiectuale permit realizarea unor clase
derivate din clase existente.

Clasa derivat motenete membrii date, metodele i

proprietile clasei de baz. n cadrul ei se pot ns aduga noi membri, date sau
metode, prin care se realizeaz practic un proces de specializare a noii clase.
La definirea unei clase derivate programatorul poate de asemenea nlocui unele
dintre metodele clasei de baz cu metode noi, mai bine adaptate.

Redefinirea

metodelor clasei de baz se mai numete i suprascriere, noile metode avnd evident
aceeai declaraie cu cele din clasa de baz.
Exemplu:
using System;
namespace TestOvr
{
class Program
{
static void Main(string[] args)
{
Derivata obj = new Derivata();
obj.Autentifica_te();
}
}
public class ClasaDeBaza
{
public void Autentifica_te()
{
Console.WriteLine("Clasa de baza");
}
}
public class Derivata : ClasaDeBaza
{
public void Autentifica_te()
{
Console.WriteLine("Clasa derivata");
}
}
}

Noua clas, Derivata a fost declarat folosind sintaxa public class Derivata :
ClasaDeBaza astfel indicndu-se relaia de derivare. n C# o clas poate avea o singur

clas printe (nu se admite motenirea multipl).


O situaie aparte apare n cazul metodelor declarate virtuale. Acestea fac posibil
un comportament normal al obiectelor declarate ca aparinnd tipului de baz i
instaniate cu obiecte aparinnd unui tip derivat. n C# la suprascrierea unei astfel de
metode se precizeaz printr-un cuvnt rezervat modul n care noua metod va opera.
Modurile posibile sunt override i new.

Diferena dintre cele dou declaraii va fi

prezentat prin dou exemple.


a. Modul override
using System;
namespace TestOvr
{
class Program
{
static void Main(string[] args)
{
ClasaDeBaza obj = new Derivata();
obj.Autentifica_te();
}
}
public class ClasaDeBaza
{
public virtual void Autentifica_te()
{
Console.WriteLine("Clasa de baza");
}
}
public class Derivata : ClasaDeBaza
{
public override void Autentifica_te()
{
Console.WriteLine("Clasa derivata");
}
}
}

Rezultat:

b. Modul new
using System;
namespace TestOvr
{
class Program
{
static void Main(string[] args)
{
ClasaDeBaza obj = new Derivata();
obj.Autentifica_te();
}
}
public class ClasaDeBaza
{
public virtual void Autentifica_te()
{
Console.WriteLine("Clasa de baza");
}
}
public class Derivata : ClasaDeBaza
{
public new void Autentifica_te()
{
Console.WriteLine("Clasa derivata");
}
}
}

Rezultat:

Tratarea excepiilor
n timpul exectrii unui program pot aprea situaii n care o eroare (denumit i
excepie program) produs ntr-un modul al programului face imposibil continuarea
acestuia. Dac uneori se pot include secvene de validare a datelor pentru ca situaiile
de eroare s fie evitate, n alte cazuri acest lucru nu este posibil sau ar complica mult
scrierea programului. O modalitate elegant de rezolvare a situaiilor care pot aprea o

constituie interceptarea prin program i tratarea excepiilor. n principiu trebuie realizat


o ncadrare n structuri try - catch a secvenelor de cod care ar putea genera erori n
timpul execuiei, dup modelul:
try
{
. . (secventa de cod generatoare de erori)
}
catch (Exception ex)
{
. . . (tratare excepie)
}

O secven de cod poate declana uneori mai multe tipuri excepii. C# permite n
aceste cazuri interceptarea separat a fiecruia dintre tipurile care ar putea aprea,
dup modelul:
try
{
. . . (secventa de cod generatoare de erori)
}
catch (NullReferenceException ex)
{
. . . (tratare excepie 1)
}
catch (ArgumentOutOfRangeException ex)
{
. . . (tratare excepie 2)
}
catch (Exception ex)
{
. . . (tratare excepie 3)
}

Aplicaia astfel structurat conine trei blocuri de tratare a excepiilor, blocul


executat stabilindu-se n mod automat n timpul execuiei. Ultimul bloc primete ca
argument un obiect din clasa Exception. Aceast clas este rdcina ierarhiei de clase
folosite la specificarea naturii excepiei, deci indiferent ce excepie este generat, dac
niciunul dintre blocurile catch n-a fost executat, se execut ultimul bloc.

Exemplu final
S vedem cum arat n C# exemplul care implementeaz o stiv i o coad.
Vom crea un proiect de tip C# Console Appllication. Codul aplicaiei va fi:
using System;
using System.Collections.Generic;
using System.Text;
namespace list
{
class Program
{
static void Main(string[] args)
{
Baza st;
Baza cd;
st=new Stiva();
cd=new Coada();
st.Afisez();
st.PUSH(1);
st.PUSH(2);
st.Afisez();
st.POP();
st.Afisez();
Console.ReadLine();
cd.Afisez();
cd.PUSH(1);
cd.PUSH(2);
cd.Afisez();
cd.POP();
cd.Afisez();
Console.ReadLine();
}
public class Elem_lista
{
private int _val;
private Elem_lista _urmatorul;
public Elem_lista(int i)
{
_val = i;
_urmatorul = null;
}
public int val
{
get
{
return _val;
}
set
{
_val = value;
}
}
public Elem_lista urmatorul
{
get
{

return _urmatorul;
}
set
{
_urmatorul = value;
}
}
}
public abstract class Baza
{
private Elem_lista _cap;
public Baza()
{
_cap = null;
}
public virtual void PUSH(int i)
{
// nu stiu cum se defineste
}
public virtual int POP()
{
// nu stiu cum se defineste
return 0;
}
public virtual void Afisez()
{
Elem_lista ptr = new Elem_lista(0);
ptr = _cap;
if (ptr == null)
Console.WriteLine(" Structura vida");
while (ptr != null)
{
Console.WriteLine(ptr.val);
ptr = ptr.urmatorul;
}
}
public Elem_lista cap
{
get
{
return _cap;
}
set
{
_cap=value;
}
}
}

public class Stiva : Baza


{
public override void PUSH(int i)
{
Elem_lista ptr = new Elem_lista(i);
ptr.urmatorul=cap;

cap=ptr;
}
public override int POP()
{
int valret;
if (cap==null)
{
Console.WriteLine("Stiva goala");
return 0;
}
valret=cap.val;
cap=cap.urmatorul;
return valret;
}
public override void Afisez()
{
Console.WriteLine("Stiva contine");
base.Afisez();
}
}
public class Coada : Baza
{
public override void PUSH(int i)
{
Elem_lista elem_nou = new Elem_lista(i);
Elem_lista ptr = new Elem_lista(0);
if (cap == null)
cap = elem_nou;
else
{
ptr = cap;
while (ptr.urmatorul != null)
ptr = ptr.urmatorul;
ptr.urmatorul = elem_nou;
}
}
public override int POP()
{
int valret;
if (cap == null)
{
Console.WriteLine("Coada goala");
return 0;
}
valret = cap.val;
cap = cap.urmatorul;
return valret;
}
public override void Afisez()
{
Console.WriteLine("Coada contine");
base.Afisez();
}
}
}

n acest exemplu, clasa de baz nu trebuie obligatoriu s fie declarat ca i


abstact, nevnd nici o metod virtual pur. Prin declaraia clasei ca abstract se
realizeaz doar imposibilitatea utilizatorului de a o instania.
O variant mai corect a implementrii acestei clase ar fi:
public abstract class Baza
{
private Elem_lista _cap;
public Baza()
{
_cap = null;
}
public abstract void PUSH(int i);
public abstract int POP();
public virtual void Afisez()
{

...
}

Aceeai claspoate utiliza i metodele grupate ntr-o interfa:


interface PushPop
{
void PUSH(int i);
int POP();
}
public abstract class Baza: PushPop
{
private Elem_lista _cap;
public abstract void PUSH(int i);
public abstract int POP();
public Baza()
{
_cap = null;
}

public virtual void Afisez()


{

...
}

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