Paradigme de programare [626448]
Paradigme de programare
•Paradigme de programare = un set de
concepte, modele si practici care descriu
esenta programarii
–Programare structurata (functionala) = un
program este conceput pe baza unei
secvente de functii, fara a avea o stare
–Programare orientata obiect = programele
sunt vazute ca fiind niste colectii de obiecte
care interactioneaza unele cu altele
Programarea structurată
•Programarea structurată -caracteristici:
•se bazează pe descompunerea func țională și abordarea top-down
(de sus în jos)
•este focalizată aproape înîntregime pe producerea de instruc țiuni
(porțiuni de cod) ne cesare rezolvării unei anumite probleme ;
proiectarea structurilor de date nu reprezintă o prioritate în această
abordare
•funcțiile care manipulează acelea și structuri de date pot diferi ca și
conven ții de numire, listă de parametri , etc.făcînd dificilă utilizarea
acestora iar codul astfel rezultat este greu de înțeles exist înd de
multe ori por țiuni semnificative de cod duplicat
•codul rezultat este dif ícil de reutilizat în alte proiecte: datorită faptului
că proiectarea începe pornind de la o problemă concretă dată ,
divizînd-oîn păr ți componente, tendin ța este aceea de a rezulta cod
specific acelei probleme particulare
•extinderea ulterioară a aplica țiilor este dificilă
Programarea orientata pe obiecte
•Programarea orientata pe obiecte => reprezinta o tehnica de
programare alternativă la programarea structurată care se bazează
pe conceptul modular de obiect. Un obiect este un fascicul de
informa ție care modelează un concept de nivel înalt din domeniul
problemei pe care o implementeză .
•abordare bottom -up (de sus in jos)
•programarea orientată pe obiecte , avînd la bază conceptul de
obiect și conceptele fundamentale de încapsulare ,moștenire și
polimorfism , prezintă următoarele avantaje :
–paradigma transmiterii de mesaje între obiecte, ca racteristică
programării orientate pe obiecte furnizează o sintaxă clară și
consistentă pentru manipularea obiectelor ;
–obiectele sunt prevăzute cu un set complet de func ții necesare și
suficiente pentru manipularea acestora
–încapsularea previne accesul neautorizat și necontrolat asupra datelor
–moștenirea permite definirea de noi structuri de date pe baza altor a
existente, reutiliz înd codul existent ( și testat)
Obiecte
•obiectul = reprezinta o componenta software
care incorporeaza atit atribute cit si operatii
(metode) care pot fi utilizate pentru manipularea
obiectului (obiectelor)
•paradigma schimbarii de mesaje intre obiecte
furnizeaza o sintaxa consistenta pentru
manipularea obiectelor => dezvoltare bazata pe
responsabilitati (responsibility -guided
development
•obiectul = reflecta concetele domeniului in cod
Obiecte
•reprezinta conceptele constructive de baza
ale sistemelor software
–un program consta dintr -o colectie de obiecte
care interactioneaza unele cu altele
–obiectele coopereaza pentru realizarea unei
anumite functionalitati prin transmiterea de
“mesaje ”unele catre altele
•sunt caracterizate de:
–capabilitati (functionalitate): ce pot sa faca
–proprietati: descriu starea obiectului
Clase
•conceptul de clasa –class –este utilizat pentru
a descrie un set de obiecte individuale la nivel
abstract
•clasa descrie proprietatile si capabilitatile
comune a setului de obiecte
•defineste un cadru (template) pentru crearea de
instante
Clase si obiecte
•clasele reprezint ǎelementele constructive de baz ǎale programelor
dezvoltate în tehnologie obiectual ǎ.
•obiectele cu care programul lucreaza sunt concepute pe baza claselor
definite în cadrul acestuia.
•obiectul reprezinta entitatea fundamentala in POO: un obiect inglobeaza o
abstractizare; un obiect in POO incapsuleaza atit o stare cit si o
functionalitate.
•obiectele reprezinta entitatile de baza ale unei aplicatii orientate pe o biecte
•programarea orientata pe obiecte poate fi văzuta ca o schimbare continua
de mesaje intre obiecte.
•obiectul , in sine, este vazut ca o masina abstracta capabila sa raspunda
acestor mesaje: totalitatea mesajelor la care este capabil sa ra spunda un
obiect este data de multimea metodelor asociate obiectului respe ctiv.
•clasa (class), serveste la descrierea, la nivel abstract, a comportar ii
obiectelor care fac parte din acea clasa. Obiectele sun t numite instantieri
sauinstan țeale acelei clase.
Concepte fundamentale
•Incapsularea = previne accesul neautorizat asupra
datelor => ascunderea informatiei
=> mentenanta mai simpla
•Mostenirea = permite definirea de noi structuri de date
pe baza celor existente, prin adaugarea de noi
caracteristici si facilitati
=> promoveaza reutilizarea codului
•Polimorfismul = permite crearea de programe mult mai
generale => promoveaza reutilizarea codului
=> utilizarea componentelor software in alte proiecte,
cu impact semnificativ asupra costurilor si costurilor de
dezvoltare ale aplicatiei
Avantajele programarii
orientate pe obiecte
Programarea orientată pe obiecte , avînd la bază
conceptul de obiect și conceptele fundamentale de
încapsulare ,moștenire șipolimorfism , prezintă
următoarele avantaje :
•paradigma transmiterii de mesaje între obiecte,
caracteristică programării orientate pe obiecte
furnizează o sintaxă clară și consistentă pentru
manipularea obiectelor;
•obiectele sunt prevăzute cu un set complet de func ții
necesare și suficiente pentru manipularea acestora
•încapsularea previne accesul neautorizat și necontrolat
asupra datelor
•moștenirea permite definirea de noi structuri de date pe
baza altora existente, reutiliz înd codul existent ( și testat)
Reutilizarea.
Limbaje orientate pe obiecte
•Reutilizarea reprezintă abilitatea unor
componente software de a putea fi utilizate la
construc ția mai multor aplica ții software diferite.
Beneficiile reutilizării se traduc în reducerea
timpul de codificare/testare și implicit a timpului
de livrare precum și a costurilor aplica ției.
•Unlimbaj orientat pe obiecte dispune de
mecanismele -suport necesare utilizarii acestui
stil de programare. Limbajul, deci, este inzestrat
cu mecanismele care fac programarea orientata
pe obiecte suficient de comoda
Exemplu –definirea unei clase cu
cimpuri de date si metode
class Punct
{
int x; //cimpurile de date
int y;
//metodele
public void set_x(int xval){x=xval;}
public void set_y(int yval){y=yval;}
public int get_x(){return x;}
public int get_y(){return y;}
}static void Main(string[] args)
{
//creaza un obiect din clasa Punct
// referinta
Punct testpt = new Punct();
int coord_x, coord_y;
//acces prin intermediul metodelor
testpt.set_x(5);
testpt.set_y(7);
coord_x = testpt.get_x();
coord_y = testpt.get_y();
Console.WriteLine("Coordonata x =
"+coord_x+" Coordonata y =
"+coord_y);
Console.ReadKey();
}
Exemplu –clase (obiecte) cu
proprietati
using System;
using System.Collections.Generic;
using System.Text;
namespace FormeGeometrie
{
class Punct
{
int m_x;
int m_y;
public int X //definire proprietatea X
{
get { return m_x; }
set { m_x = value; }
}
public int Y //definire proprietatea Y
{
get { return m_y; }
set { m_y = value; }
}
}class Program
{
static void Main(string[] args)
{
//creare obiect din clasa Punct
//referinta
Punct testpt = new Punct();
testpt.X=5; //setarea proprietatii X
testpt.Y=7; //setarea proprietatii Y
//afisare proprietati
Console.WriteLine("Coordonata x =
"+testpt.X+" Coordonata y =
"+testpt.Y);
Console.ReadKey();
}
}
}
Cimpuri si proprietati
•pentru c împuri se rezerv ǎloc de memorie, acestea con ținînd datele propriu -zise ale
unei clase.
•propriet ǎțileoferǎdoar acces la date, dar nu reprezint ǎdatele propriu -zise.
•propriet ǎțile par s ǎatenueze diferen țaîntre cod și date: pentru un program care
utilizeaz ǎo clas ǎ, propriet ǎțile arat ǎca ni ște cîmpuri de date, chiar dac ǎele
reprezint ǎde fapt cod. În multe situa ții, o proprietate public ǎasigur ǎaltor clase
accesul la un c împ privat al clasei.
•proprietatea are, spre deosebire de c împ, avantajul c ǎpoate face în plus și verific ǎri
de validitate.
•propriet ǎțile pot fi private sau publice, de tip read/write ,read-only sauwrite -only.
•în C#, propriet ǎțile nu pot avea parametri ( în Visual Basic, de exemplu, acest lucru
fiind posibil)..
•sintaxa general ǎpentru o proprietate de tipul read/write este urm ǎtoarea:
public tip_proprietate NumeProprietate
{
get{ aici se returneaza o valoare }
set{ aici se atribuie o valoare }
}
Structura generala a unei clase
•cîmpuri de date
•proprietă ți
•metode –inclusiv constructori și destructor
•elemente de indexare
•delega ți
•evenimente
•eventual, alte clase încuibate
Clase incuibate
•Clasele încuibate sunt declarate în interiorul
unor alte clase; în esen ță, ele se comportă
cași clasele obi șnuite, pot con ține metode și
cîmpuri de date, etc.:
class Clasa_Incuibata
{
public int membru_out;
public static int alt_membru_out = 13;
//definire clasa incuibata
public class Incuibata
{
int membru_in;
public Incuibata()
{
membru_in = 0;
}
public int Membru_In()
{
return membru_in;
}
}
}•Instan țierea unui obiect dintr -o clasă
încuibată poate fi realizată astfel :
Clasa_Incuibata.Incuibata obj =
new Clasa_Incuibata.Incuibata();
Console.WriteLine("Valoarea membru_in =
"+obj.Membru_In());
Console.WriteLine("Valoarea alt_membru_out =
"+Clasa_Incuibata.alt_membru_out);
•Metodele clasei încuibate pot accesa to ți
membri acesteia dar nu pot accesa dec ît
membri statici ai clasei exterioare (deci,
accesul la alt_membru_out este posibi în
schimb la membru_out nu). În consecin ță,
nu este necesar să existe o instan ță a clasei
exterioare pentru a crea o instan ță a clasei
încuibate. De asemenea, crearea unei
instan țe a clasei exterioare nu implică
crearea unei instan țe a clasei încuibate.
Structuri in C#
using System;
using System.Collections.Generic;
using System.Text;
namespace Structuri
{
struct Coordonate
{
public int x;
public int y;
public Coordonate(int x, int y)
{
//evitarea conflictelor de nume folosind this
this.x = x;
this.y = y;
}
public Coordonate Deplaseaza
(Coordonate pt)
{
// crearea unei variabile struct fără instan țiere cu new
Coordonate nou;
nou.x = x + pt.x;
nou.y = y + pt.y;
return nou;
}
}class Program
{
static void Main(string[] args)
{
Coordonate punct1 = new Coordonate(10, 20);
Coordonate deplasare = new Coordonate(20, 35);
Coordonate punct2;
punct2 = punct1.Deplaseaza(deplasare);
Console.WriteLine("noile coordonate punct2:
x= "+ punct2.x + " y = " + punct2.y);
Console.ReadKey();
}
}
}
• variabilele de tip struct pot fi instan țiate cu new, desi
acest lucru un e necesar
• structurile pot fi utilizate ca și tipurile valoare:
• structurile nu pot avea destructori
• structurile nu pot mo șteni sau nu pot fi mo ștenite ,
cașiîn cazul claselor; în schimb, structurile pot
implementa una sau mai multe interfe țe
• în general, utilizarea structurilor implică un
overhead mai mic dec ît alternativa claselor, datorită
faptului că acestea sunt tip valoare (stocate pe
stivă)și nureferin ță(stocate în heap).
Spatii de nume (1)
•un spa țiu de nume în MicroSoft . NET este asemănător cu un
container de obiecte.
•poate con ține o serie de elemente precum: clase, structuri,
interfe țe, enumeratori, delega ți
•utilizat pentru organizarea ierarhică a programelor , care are ca și
consecin ță directă evitarea conflictelor de nume în cadrul unui
proiect complex (nume de clase, func ții, variabile)
•în MicroSoft .NET, fiecare program este creat împreună cu un
spațiu de nume implicit, a șa numitul spa țiu de nume global. În
cadrul programului însă pot fi create și alte spa ții de nume, fiecare
cu un nume distinct, și con ținînd propriile clase, func ții, variable
sau chiar alte spa ții de nume, al căror nume trebuie să fie unic în
cadrul spa țiului de nume respectiv.
•conceptul de spa țiu de nume ( namespace ) faciliteaz ǎde
asemenea utilizarea bibliotecilor de clase de la diver și furnizori și
care ar putea con ține clase cu nume similare. Pentru declararea
unui spa țiu de nume în C# se utilizează cuv întul cheie
namespace .
Spatii de nume (2)
namespace Compania1.BibliotecaUtila
{
..
class ClasaUtila {….}
}
namespace Compania2.BibliotecaExtinsa
{
..
class ClasaUtila {….}
}
Compania1.BibliotecaUtila.ClasaUtila
Compania2.BibliotecaExtinsa.ClasaUtil ǎ
•MicroSoft .NET Framework define ște peste 90 de spa ții de nume care încep
cu cuv întul System și 5 spa ții de nume care încep cu cuv întul MicroSoft:
System, System.Drawing, System.Windows.Forms, etc. -fiecare clas ǎ
definit ǎîn cadrul unui proiect va fi plasat ǎîn cadrul unui spa țiu de nume
propiu proiectului și se specific ǎprin directiva using ce spa ții de nume
utilizeaz ǎclasa respectiva
•spațiile de nume permit de asemenea atribuirea de nume existente dej aîn
.NET Framework în cadrul programelor dezvoltate.directiva using utilizată
pentru a se specifica, la
începutul programului, la ce
spațiu sau spa ții de nume
se face referire (se dore ște
utilizarea claselor incluse î
n cadrul acelor spa ții de
nume)
Încapsularea
și controlul accesului (1)
•încapsularea implică faptul că structura internă a obiectului este
ascunsă total sau par țial de obiectele din exteriorul său ; accesul se
realizează prin intermediul a șa numitei interfe țe publice a obiectului
respectiv în mod controlat și sigur.
•încapsularea presupune reuniunea în cadrul claselor a structurilor de
date împreună cu codul necesar prelucrării acestor structuri .
Încapsularea implică modularitate , si reprezintă mecanismul prin care se
combin astructuri de tip inregistrare (c impuri de date) cu proceduri si
functii (metode) care manipulează c impurile de date ale structurilor,
formind un nou tip de date numit clasa.
•private, protected sipublic controlează accesul at it la c impurile unui
obiect c itsi la metodele și propietă țile acestuia, in urm atoarea manier a:
•Private -elementele sunt direct accesibile numai in interiorul clasei;
altfel, din exterior accesul trebuie s ase fac anumai prin metode definite
explicit, și care nu sunt private (publice sau protected, dup ǎcaz). In mod
automat, dac ǎnu se specific ǎnimic în acest sens, in C# elementele
respective (c împuri de date, pro prietă ți sau metode) se consider ǎimplicit
private; totu și este indicată precizarea explicită a acestuia .
•Protected -reprezint anivelul doi de acces, mai pu tin restrictiv dec it
private , care permite membrilor claselor derivate sa aib eacces direct la
datele private ale claselor stramo si
Încapsularea
și controlul accesului (2)
•Public -reprezinta nivelul trei de acces, in mod normal utilizat numai
pentru metode sau propriet ǎți,si care confera acestora proprietatea de a
fi accesate in mod direct, de oriunde din afara obiectului. Metodele nestatic e
definite în cadrul unei clase se apeleaza prin intermediul obiectelor defi nite
din clasa respectiv ǎ, prin intermediul nota ției generale “cu punct ”:
nume_obiect.nume_metoda(..parametri…) sau
nume_obiect.nume_proprietate
•internal permite accesul prin program numai în cadrul aceluia și ansamblu;
modificatorul internal este de regulă utilizat în cazul în care se crează o
bibliotecă de clase pentru a restric ționa accesul din afară la codul declarat
internal .
•protected internal reprezintă o combina ție a celor doi modificatori implica ți
adică și protected și internal: permite accesul din cadrul aceluia și ansamblu
darși din clase derivate care nu fac parte din acela și ansamblu.
•modificatorii de acces pot fi aplica țiși tipurilor de date (claselor); însă tipurile
de date acceptă doar doi modificatori de acces :public șiinternal (implicit);
internal implică accesul numai la tipurile definite în cadrul aceluia și
ansamblu ( assembly ).
Structura generala a unui
program C#
using System;
namespace UnNamespace
{
class OClasa
{ … }
struct OStructura
{ … }
interface OInterfata
{ … }
delegate int UnDelegat();
enum OEnumerare
{ … }
namespace UnNamespaceIncuibat
{
struct OStructura
{ … }
}
class ClasaMain
{
static void Main(string[] args)
{ //…
}
}
}•Observa ție:în C# nu sunt permise metode și
variabile globale: acestea trebuie s ǎfie con ținute fie
într-o clas ǎsauîntr-o structur ǎ
•aplica țiile C# sunt constituite din mai multe fi șiere;
fiecare fi șier poate con ține mai multe spa ții de nume
•in cadrul unui spa țiu de nume sunt definite tipurile
necesare aplica ției care pot fi de urm ǎtoarele
categorii: clase, structuri (struct), interfe țe,
enumer ǎri, delega ți. Spațiul de nume ( namespace )
poate con ține mai multe clase cu nume diferite și
funcționalită țiînrudite.
•în cadrul unui spa țiu de nume mai poate apărea
defini ția unui alt spa țiu de nume, caz în care avem
de-a face cu spa ții de nume imbricate
•mai pot fi definite de asemenea structuri, interfe țeși
delega ți.
•pentru a facilita dezvoltarea aplica țiilor complexe, la
care, de regulă , sunt implica ți mai mul ți
programatori, exis tă posibilitatea de a segmenta
aplica țiaîn mai multe fi șiere a șa numitele
ansambluri ( assembly ).Într-un ansamblu se pot
implementa mai multe spa ții de nume sau păr ți ale
aceluia și spa țiu de nume se pot regasi în mai multe
ansamble.
Constructori
•un constructor este un bloc de cod care se execut ǎatunci c înd se
utilizeaz ǎcuvîntul cheie new pentru a crea o instan țǎa unei clase;
•rezultatul apel ǎrii constructorului îl reprezint ǎcrearea unei variabile
de tip referin țǎ
•constructorii trebuie sa aibe acelasi nume cu clasa insasi a
obiectului.
•se definesc și se utilizează în principiu ca și func țiile membre
obișnuite; fa ță de acestea însă, constructorii sunt implicit apela ți
atunci c înd se crează obiecte ale clasei respective .
•constructorii nu returneaza nici un fel de valoare, nici macar d e tipul
void;
•atunci c înd nici un constructor nu este definit în cadrul unei clase,
compilatorul genereaz ǎun constructor implicit, ca metod ǎpublic ǎ;
•constructorii pot avea multiple definitii, rezultind ceea ce se numeste
supraincarcarea constructorilor ( overloading ); deosebirea dintre
aceștiași selec ția efectiv ǎa constructorului apelat la un moment dat
este realizat ǎde cǎtre compilator pe baza num ǎrului și/sau tipul
parametrilor actuali furniza țiîn momentul apelului
•constructorii nu se mostenesc de catre descendenti ca si alte
metode
Constructorii implici ți
•se pot ob ține fie prin declararea de către utilizator al unui constructor
simplu, fără nici un parametru , indiferent de instruc țiuni, fie prin generarea
implicită a acestuia de către compilator , atunci c înd clasa respectivă nu are
nici un constructor.
public Punct() { }
•pentru obiectele create sub forma unor structuri de tablou de ob iecte
trebuie să existe un constructor fără parametri ,în caz contrar semnal îndu-
se eroare
static void Main(string[] args)
{
Punct[] figura = new Punct[20];
//definire tablou de 20 de obiecte din clasa Punct
//apel implicit la constructorul implicit al clase i Punct
}
Constructori cu parametri
•inițializarea c împurilor de date se face pe baza valorilor
primite ca și parametri de către constructor
public Punct(int x, int y)
{
m_x = x;
m_y = y;
}
static void Main(string[] args)
{
Punct testpt = new Punct(7, 5);
}
Constructori de copiere
•atunci c înd se copiază un obiect într-un alt obiect, C#copiază de
fapt referin ța primului obiect în al doilea, ceea ce conduce la crearea
a două referin țe către acela și obiect.
•dacă se dore șteînsă crearea unei instan țe-copii ale unui obiect
existent se poate utiliza un constructor de copiere.
•constructorul de copiere prime ște ca parametru un obiect din clasa
respectivă și crează un al doilea obiect ca și o copie a obiectului
primit ca parametru.
public Punct(Punct p)
{
this.m_x = p.m_x;
this.m_y = p.m_y;
}
Exemplu
using System;
using System.Collections.Generic;
using System.Text;
namespace FormeGeometrie
{
class Program
{
static void Main(string[] args)
{
Punct pt = new Punct(20, 30);
// obiect nou -copie creata utilizind
//constructorul de copiere
Punct pt_copie =
new Punct(pt);
Punct pt_alta_copie;
//referintele indica acelasi obiect
pt_alta_copie = pt;//modificam valorile X si Y pentru pt
pt.X = 10;
pt.Y = 15;
Console.WriteLine
("Punctul original de
coordonate X = " + pt.X +
" Y = " + pt.Y);
Console.WriteLine(
"Punctul copiat de
coordonate X = " +
pt_copie.X +
" Y = " + pt_copie.Y);
Console.WriteLine(
"Punctul atribuit de
coordonate X = " +
pt_alta_copie.X +
" Y = " +
pt_alta_copie.Y);
Console.ReadKey();
}
}
}
Destructori
•destructorii sunt utiliza ți pentru a distruge o instan țǎa unui obiect
•destructorii nu se mo ștenesc; de fapt, se poate defini un singur
destructor pentru o clas ǎ, fǎrǎparametri
•destructorii în C# nu pot fi apela țiîn mod explicit, ei sunt apela ți
automat; programatorul nu are nici un control asupra momentului
cînd destructorul este apelat pentru c ǎacest lucru este realizat de
cǎtrecolectorul de de șeuri care, dac ǎconsider ǎcǎun obiect
poate fi distrus, apeleaz ǎdestructorul (dac ǎexistǎ).
•destructorii sunt de asemenea apela ți atunci c înd programul se
termin ǎ
~Punct()
{
Console.WriteLine("Acum s -a apelat
destructorul clasei Punct!");
}
Destructorii si metoda Finalize
•destructorii C# sunt converti ți către un apel la metoda Finalize
(care nu poate fi apelată direct din C #) a clasei System.Object
~Nume_destructor()
{
// cod destructor
}
protected override void Finalize()
{ try
{
//cod destructor
}
finally
{
base.Finalize();
}
}
Mecanismul de colectare a de șeurilor
(garbage collection )
•dacǎnimic dintr -un program nu mai face referire la blocul de memorie ini țial,
acesta devine candidat pentru opera ția de colectare a de șeurilor (sau
eliberare a memoriei neutilizate –garbage collection ).
•MicroSoft .NET Framework gestioneaz ǎmemoria prin intermediul unei
rutine de colectare a de șeurilor. Tipurile referin țǎsunt alocate în memoria
heap gestionat ǎde instrumentul Common Language Runtime CLR.
•rutina de colectare a de șeurilor urm ǎrește utilizarea obiectelor: c înd nu mai
existǎreferin țe cǎtre un obiect, aceasta va marca memoria utilizat ǎde
obiectul respectiv ca disponibil ǎpentru reutilizare, iar, ulterior, va cur ǎța
memoria heap și realiza anumite opera țiuni de compactare a acesteia,
compactare (deplasarea obiectelor existente în memorie (!))
•rutina de colectare a de șeurilor utilizeaz ǎunmecanism de tip genera țieîn
cadrul c ǎruia obiectele care “supravie țuiesc ”unei colect ǎri sunt trecute
într-o genera ție mai veche. Folosirea mecanismului de colectare a
deșeurilor izoleaz ǎprogramatorul de detaliile aloc ǎrii memoriei șiîl scute ște
de responsabilitatea eliber ǎrii acesteia
•teoretic, programatorul nu cunoa ște momentul exact c înd rutina de
colectare a de șeurilor va fi lansată în execu ție; practic, se poate for ța
lansarea în execu ție a acesteia printr -un apel explicit la
System.GC.Collect ; un astfel de apel trebuie realizat cu precau ție
deoarece poate avea consecin țe nedorite asupra vitezei de execu ție
Țintuirea pointerilor
using System;
using System.Collections.Generic;
using System.Text;
namespace Pointeri
{
class Prima
{
public int i;
}
class Secunda
{
static unsafe void
UtilPointeri(Prima pr)
{
//definire obiecte țintuiteîn blocuri a șa
//numitefixe(fixed):
fixed (int *p = &pr.i)
Console.Writeline
("Pointer la {0:x}", (int)p);
}
}class Program
{
static void Main(string[] args)
{
Prima pr = new Prima();
pr.i = 0;
Secunda.UtilPointeri(pr);
}
}
}
Obs:
Pentru a func ționa corect, programul
trebuie compilat cu op țiunea / unsafe .
Porțiunile de cod marcate cu unsafe
nuînseamn ǎneap ǎrat cǎsunt
periculoase, ci doar c ǎacestea nu pot
fi verificate de c ǎtre instrumentul
Runtime din mediul .NET: Coommon
Language Runtime –CLR
Tipuri referin țãși tipuri valoare
Tipuri valoare
O variabil ǎde tip valoare se creaz ǎ
atunci c înd se declar ǎo variabil ǎ:
•de un tip integral (int)
•de un tip în virgul ǎmobil ǎ(double)
•de un tip boolean (bool)
•de tip enumerare (enum)
•de tip structur ǎ(struct)
Practic, majoritatea tipurilor simple
înC# sunt de tip valoare:
bool, char, byte,
sbyte, short, ushort, int, uint,
long, ulong, float, double,
decimal .Tipuri referin ță
O variabil ǎde tip referin țǎse creaz ǎ
atunci c înd se declar ǎ:
•un obiect dintr -o anumit ǎclasǎ
inclusiv clasa Object
•o variabilă de tip interfa țǎ
(interface)
•un tablou (array)
•unșir (string)
•un delegat (delegatul este de fapt
un obiect care con ține informa ții
despre o metod ǎcare va fi
apelat ǎla apari ția unui anumit
eveniment
•o variabilă referin ță care un referă
nimic este asignată implicit cu
valoarea null(null reference ).
Tipul (clasa) Object
•Equals – indică faptul că două instan țe de tip Object sunt egale.
Implementarea implicită tertează doar egalitatea referin țeiși
returnează true dacă ambele referin țe punctează către acela și
obiect. Pentr u tipurile valoare este testată egalitatea la nivel de bit .
Clasele derivate trebuie să redefinească metoda pentru a -și defini
propria modalitate de testare a egalită ții pentru obiectele proprii
•GetHashCode – reprezintă o func ție de dispersie pentru obiectul
curent
•GetType – returnează tipul Type a instan ței cure nte a obiectului
curent
•ReferenceEquals -determină dacă două referin țe indică spre
acelea și obiect
•ToString – returnează un String care este reprezentarea sub formă
deșir de caractere pentru obiectul curent
Tablouri in C# (1)
Tablouri unidimensionale
int[] tab_uni = new int[2];
tab_uni[0] = 1;
tab_uni[1] = 2;
// alte posibilitati de initializare a tabloului
int[] tab_uni = new int[] { 1, 2 };
int[] tab_uni = { 1, 2 };
Obs. variabila tablou creată dispune de o serie de metode (clasa System.Array) prin care
se pot realiza diferite opera ții asupra elementelor tabloului.
Console.WriteLine( "Dimensiunea tabloului =
"+tab_uni.GetLength(0));
Tablourile multidimensionale rectangulare – reprezintă tablouri care au mai multe
dimensiuni fixate prin declara ția tabloului :
//declarare tablou multidimensional rectangular 2×3 fara ini tializare
int[,] tab_bi_0 = new int[2, 3];
//declarare tablou bidimensional cu initializare
int[,] tab_bi = { { 1, 2, 3 }, { 4, 5, 6 } };
for (int i = 0; i < tab_bi.GetLength(0); i++)
for (int j = 0; j < tab_bi.GetLength(1); j++)
Console.WriteLine(tab_bi[i, j]);
Tablouri in C# (2)
Tablourile multidimensionale (jagged) -sunt de fapt tablouri multidimesionale dar cu
dimensiuni neregulate. Flexibilitatea în acest caz derivă din aceea că tablourile sunt
imlementate ca tablouri de tablouri
//creare tablou jagged fara initializare
int[][] tab_jag = new int[2][];
tab_jag[0] = new int[4];
tab_jag[1] = new int[6];
//creare tablou jagged cu initializare
int[][] tab_jag = new int[][]
{ new int[] { 1, 2, 3, 4 },
new int[] { 5, 6, 7, 8, 9, 10 } };
//accesare elemente tablou utilizind Length
for (int i = 0; i < tab_jag.Length; i++)
for (int j = 0; j < tab_jag[i].Length; j++)
Console.WriteLine(tab_jag[i][j]);
Mecanismul împachetare/despachetare
(boxing/unboxing)
•împachetarea reprezint ǎtransformarea unui tip valoare în tip
referin țǎ, creînd un nou obiect în memoria heap gestionat ǎcare are
acelea și cîmpuri ca și tipul valoare; instrumentul Common Language
Runtime (CLR) creaz ǎun astfel de obiect șiîl inițializeaz ǎcu
cîmpurile și valorile din tipul valoare.
int i = 10;
i.ToString();
•compilatorul crează o instan ță a clasei Object care con ține valoarea
întreagă i (împachetare implicită ).Apoi se realizează apelul către
metoda ToString folosindu -se instan ța creată a obiectului
int i = 10;
Object obj = i;
obj.ToString();
•despachetarea implic ǎopera ția invers ǎ: adic ǎcrearea unui tip
valoare dintr -un tip referin țǎ; despachetarea însă presupune
transformarea explicită dintr-un obiect într-un tip valoare:
int i = (int) obj;
Exemplu
using System;
using
System.Collections.Generic;
using System.Text;
namespace Pachet
{ class Program
{ public struct Valoare
{
public int x;
public int y;
}
•obiectul împachetat ac ționeaz ǎca un
container în cadrul c ǎruia se regase ște
o copie a tipului valoare pe care îl
împacheteaz ǎ; utilizarea func ției
GetType() va returna acela și tip at ît
pentru obiectele ne împachetate c îtși
pentru cele împachetate.
•în general, GetType() returneaz ǎun
obiect de tipul Type, o clas ǎdefinit ǎîn
spațiul de nume System. GetType()
•Clasa Type permite ob ținerea de
informa ții despre un anumit obiect,
inclusiv metodele, c împurile de date și
propriet ǎțile acestuia.static void Main(string[] args)
{
//variabila tip valoare
Valoare a;
a.x = 1;
a.y = 2;
Object o = a;
// atribuire catre tipul referinta
Console.WriteLine
("Tipul variabilei o este “
+o.GetType()); //referinta
Console.WriteLine
("Tipul variabilei a este “
+a.GetType()); //Valoare
if ((((Valoare)o).x == a.x)
&&(((Valoare)o).y == a.y))
Console.WriteLine
("Impachetare reusita!");
}
}
}
Obs. Operatorul typeof returneaz ǎde asemenea un
obiect de tipul Type; diferen ța dintre cele dou ǎ
const ǎdin aceea c ǎGetType() este aplicat ǎunui
obiect iar typeof se aplic ǎunei clase.
Împachetarea și
conversiile de tip
•împachetarea și despachetarea reprezintă transformări
între tipul valoare și referin ță(obiect) în timp ce
conversiile de tip transformă tipul (aparent) al obiectului
•tipurile valoare sunt memorate în stivă în timp ce
obiectele sunt memorate în heap
•împachetarea preia o copie a tipului valoare de pe stivă
în heap iar despachetarea repune tipul valoare pe stivă .
•conversiile de tip pe de altă parte nu realizează nici un
fel de mutări fizice ale obiectelor , doar schimbă modul în
care acestea sunt tratate de program prin modificarea
tipului referin ței
Utilizarea membrilor statici (1)
•se realizează utiliz înd cuv întul cheie static.
•cîmpuri de date statice : acest lucru înseamnă că toate instan țele claselor
respective împart acela și membru static, practic se aloc ǎo singur ǎdatǎ
memorie, o sing ură zonă comună tuturor obiectelor clasei ; fiecare instan țǎa
clasei are acces la copia unic ǎa datelor statice.
•propriet ǎțileși metodele pot fi la r îndul lor declarate statice: acestea sunt de
regul ǎutilizate pentru a prelucra datele statice ale clasei.
•propriet ǎțileși metodele statice (inclusiv constructorii) prezint ǎdezavantajul c ǎ
nu pot utiliza în cadrul implement ǎrii dec îtcîmpurile declarate statice ale
clasei din care fac parte, neav înd acces la niciuna din datele instan țelor clasei
respective (dac ǎexistǎvreuna).
•în cazul constructorilor declara ți static, ace știa sunt apela țiînainte ca orice
membru static al clasei respective să fie referit , astfel încît ace știa pot fi utiliza ți
la inițializarea clasei, nu doar a obiectelor; constructorii declara ți static nu pot
avea parametri
•se caracterizeaz ǎdeci prin faptul c ǎaparțin clasei propriu -ziseși nu unui obiect
al unei anumite clase => datele statice pot fi ini țializate chiar dac ānu exist ǎîncǎ
obiecte instan țiate, prin intermediul clasei; se aplic ǎregulile generale de acces.
nume_clasa.cimpul de date_membru_static=valoare;
nume_clasa.nume_metoda_statica(..);
Utilizarea membrilor statici (2)
•există clase , precum clasa System.Math , care con țin numai membri statici;
in acest caz, este de dorit să nu se permită crearea de instan țe a clasei
respective; o meto dă de a realiza acest lucru este aceea de a crea un
constructor private, care bloc hează crearea constructorului implicit și un
este accesibil din afara clasei, făcînd astfel imposibilă crearea de obiecte
din acea clasă .
•declararea unor membri statici este utilă , deoarece ea reprezintă solu ția
optimă în cazul în care obiectele unei clase folosesc date în comun,
reduc îndu-se astfel numărul de variabile globale .
•utilizarea membrilor statici rezolv ǎnumeroase situa țiiîn programare, însǎ
trebuie folosi ți cu precau ție: datele statice publice sunt disponibile în orice
metod ǎîn care clasa este vizibil ǎ, devenind astfel globale. Astfel accesul la
acestea și implicit modific ǎrile aferente devin incontrolabile, lucru care
trebuie, pe c ît posibil evitat.
Exemplu (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace FormeGeometrie
{
class Punct
{
static Punct m_centru
= new Punct(0, 0);
public static Punct Centru
{
get {return m_centru;}
set {m_centru=value;}
}
//defineste centrul sistemului,
//de unde se calculeaza distanta
int m_x;
int m_y;
public Punct()
{ }
public Punct(int x, int y)
{
m_x = x;
m_y = y;
}public int X //proprietatea X
{
get { return m_x; }
set { m_x = value; }
}
public int Y //proprietatea Y
{
get { return m_y; }
set { m_y = value; }
}
public int DistantaLaPatrat()
{
int distx = m_centru.X -m_x;
int disty = m_centru.Y -m_y;
return (distx * distx) +
(disty * disty);
}
public static void ModificaCentru
(int xc, int yc)
{
m_centru.X = xc;
m_centru.Y = yc;
}
}
}
Exemplu (2)
class Program
{
static void Main(string[] args)
{
Punct testpt = new Punct(5,7);
//calcul distanta fata de (0,0)
Console.WriteLine("Distanta la patrat fata de centru
= "+testpt.DistantaLaPatrat());
//modificare valoare membru static
Punct.Centru.X = 2;
Punct.Centru.Y = 2;
//calcul distanta fata de (2,2)
Console.WriteLine("Distanta la patrat fata de centru = “
+ testpt.DistantaLaPatrat());
//modificare cimp static prin intermediul metodei statice
Punct.ModificaCentru(3, 4);
Console.WriteLine("Distanta la patrat fata de centru = "
+ testpt.DistantaLaPatrat());
Console.ReadKey();
}
}
Moștenirea și ierarhia de clase –
concepte de bază
•moștenirea reprezinta mecanismul
care premite crearea unei ierarhii
de obiecte cu descendenti, care
mostenesc accesul si structurile
de date ale stramosilor.
•prin intermediul mo ștenirii se pot
reutiliza și extinde clasele
existente, fără a rescrie codul
original; diferen ța fundamentală
între limbajele de programare
structurate și cele orientate pe
obiecte o reprezintă tocmai
utilizarea conceptului de
moștenire
•în programarea obiectuală se
admite compatibilitatea între tipul
clasei derivate și tipul clasei de
bază , reciproca nefiind însă
adevărată•C#suportă numai mo ștenire
simplă : acest lucru implică faptul
că o clasă poate să fie derivată
dintr-o singură clasă de bază
Partea mostenita
de la X
Partea specifica
lui YY = clasa
derivata din X
(copil)X = clasa
de baza (parinte)
Moștenirea și apelul constructorilor
și destructorilor
•întotdeauna clasa de bază este instan țiatăînaintea clasei derivate:
constructorul clasei de bază este apelat înaintea celui din clasa
derivată
•întotdeauna la crearea unui obiect dintr -o clasă derivată se apeleaza
întîi constructorul clasei de bază
•toate clasele din C# și .NET Framework sunt derivate dintr -o clas ǎ
Object sau dintr -o clas ǎderivat ǎdin clasa Object. Astfel se poate
spune de fapt c ǎtoate clasele sunt derivate din Object
Exemplu -clasa Baza
class Baza
{
int m_Baza;
public Baza()
{m_Baza = 0;
Console.WriteLine
("Constructorul
clasei Baza fara
parametru");
}
public Baza(int p)
{
m_Baza = p;
Console.WriteLine
("Constructorul
clasei Baza cu
parametru");
}public void Afisare()
{
Console.WriteLine
("Clasa Baza m_Baza
= " + m_Baza);
}
public void Metoda_Baza()
{
Console.WriteLine
("Metoda proprie
a clasei Baza");
}
}
Exemplu -clasa Derivata
class Derivata:Baza
{
int m_Derivata;
public Derivata()
{
m_Derivata = 0;
Console.WriteLine
("Constructorul clasei
Derivata fara
parametru");
}
public Derivata
(int b, int d):base(b)
{
m_Derivata = d;
Console.WriteLine
("Constructorul clasei
Derivata cu
parametru");
}public void Afisare()
{
base.Afisare();
Console.WriteLine
("Clasa derivata ”
+m_Derivata);
}
public void Metoda_Derivata()
{
Console.WriteLine
("Metoda proprie a
clasei Derivata");
}
}
Exemplu -Main
class Program
{
static void Main(string[] args)
{
Baza obj_baza1 = new Baza();
Baza obj_baza2 = new Baza(5);
Derivata obj_deriv1 = new Derivata();
Derivata obj_deriv2 = new Derivata(7, 8);
obj_baza2.Afisare();
obj_deriv2.Afisare();
obj_deriv1.Metoda_Derivata();
obj_deriv1.Metoda_Baza();
Baza obj_baza3 = new Derivata(10, 15);
obj_baza3.Afisare();
Console.ReadKey();
}
}
Moștenirea și implementarea
constructorilor și destructorilor
•deoarece scopul claselor derivate este acela de a adăuga noi
caracteristici claselor de bază ,în mod evident constructorii acestora
sunt mai complec și
•abordarea utilizată în acest sens este ca ace știa să apeleze în mod
implicit sau explicit constructorii claselor de bază ori de c îte ori este
posibil
•regula este următoarea :în cazul constructorilor, se apelează mai
întîi constructorii claselor de bază , apoi se execută ac țiuni specifice
constructorului clasei derivate .
Punct
Cerc
DreptunghiPatrat
Exemplu –clasa Punct
class Punct
{
int m_x;
int m_y;
//proprietatea X
public int X {
get { return m_x; }
set { m_x = value; }
}
//proprietatea Y
public int Y
{
get { return m_y; }
set { m_y = value; }
}
//constructori pentru clasa Punct
public Punct()
{ }public Punct(int x, int y)
{
m_x = x;
m_y = y;
}
virtual public string IsA
{
get { return "Punct"; }
}
virtual public void
Deseneaza()
{
Console.WriteLine("Deseneaza
un punct!");
}
}
Exemplu –clasa Patrat
class Patrat:Punct
{
int m_latura;
public int Latura
{
get { return m_latura; }
set { m_latura = value; }
}
//constructori pentru clasa Patrat
public Patrat()
{ }
public Patrat
(int x, int y, int latura)
:base(x,y)
{
m_latura = latura;
}//metode redefinite ca override
public override string IsA
{
get { return "Patrat"; }
}
public override void
Deseneaza()
{
Console.WriteLine
("Deseneaza
un patrat!");
}
}
Exemplu –clasa Dreptunghi
class Dreptunghi:Punct
{
int m_lungime;
public int Lungime
{
get { return m_lungime; }
set { m_lungime = value; }
}
int m_latime;
public int Latime
{
get { return m_latime; }
set { m_latime = value; }
}
//constructori pentru clasa Dreptunghi
public Dreptunghi()
{ }public Dreptunghi
(int x, int y, int lungime,
int latime):base(x,y)
{
m_lungime = lungime;
m_latime = latime;
}
//metode redefinite ca override
public override string IsA
{
get { return "Dreptunghi";}
}
public override void
Deseneaza()
{
Console.WriteLine
("Deseneaza un
Dreptunghi!");
}
}
Exemplu –clasa Cerc
class Cerc:Punct
{
int m_raza;
public int Raza
{
get { return m_raza; }
set { m_raza = value; }
}
//constructori pentru clasa Cerc
public Cerc()
{ }
public Cerc(int x, int y, int
raza):base(x,y)
{
m_raza = raza;
}//metode redefinite ca override
public override string IsA
{
get { return "Cerc"; }
}
public override void
Deseneaza()
{
Console.WriteLine("Deseneaza
un cerc!");
}
}
Exemplu –Main
class Program
{
static void Main(string[] args)
{
//apel explicit la constructorul cu parametru al clasei Punct
Patrat p = new Patrat(8,3,20);
Cerc c = new Cerc(7,10,40);
Dreptunghi d = new Dreptunghi(2,7,30,50);
Console.ReadKey();
}
}
Modificatorii abstract șisealed
•obligă respectiv se opun procesului de mo ștenire.
•o clasă declarată abstractă (abstract ) trebuie neapărat derivată ,
pentru că ea însăși nu poate fi instan țiată
abstract class Clasa_abstracta
{ … }
•o clasă declarată ca sigilată (sealed ) nu mai poate fi derivată
ulterior, practic ea trebuie văzută ca o clasă terminală din cadrul
ierarhiei; derivare a unei clase dintr -o clasă sigilată , compilatorul va
genera o eroare
sealed class Clasa_terminala
{ … }
•într-o manieră asemănătoare , modificatorii abstract șisealed pot fi
aplica țiși metodelor, în acest context ei impun îndrespectiv
interzic îndredefinirea metodei respective în cadrul claselor derivate
Mecanismul polimorfismului (1)
•polimorfismul reprezintă abilitatea claselor
de a furniza implementări diferite pentru
metodele care sunt apelate cu acela și
nume.
•polimorfismul permite apelul unei metode a
unei clase indiferent de implementarea
acesteia.
•mecanismul care stă la baza
polimorfismului îl reprezintă posibilitatea de
a referi obiecte -derivate prin intermediul
unor referin țe către clasa de bază =>este
corectă asignarea :
Baza b = new Derivata();
•obiectul de tip Derivata este tratat ca un
obiect de tip Baza, ceea ce este corect
întruc ît Derivata este un sub -tip sau tip
derivat a lui Baza:
b.Metoda_Baza(); //corect
b.Metoda_Derivata(); //eroare
•accesul la metoda proprie a clasei Baza
este corect; în schimb, metoda proprie a
clasei Derivata nu este accesibilă deoarece
b este tratat ca fiind de tip Baza.class Baza
{
public void Metoda_Baza() { … }
public void Metoda_Comuna() { … }
}
class Derivata: Baza
{
public void Metoda_Derivata() { … }
public void Metoda_Comuna() { … }
}
•dacă însă se încearcă accesul la metoda
comună a celor două clase , compilatorul va
genera un warning prin care ne aten ționează că
Metoda_comuna din Derivata ascunde
Metoda_comuna moștenita de la clasa Baza.
•in acest caz, se va afi șa totu și metoda
Metoda_comuna a clasei Baza:
Baza b = new Derivata();
b.Metoda_Comuna();
Mecanismul polimorfismului (2)
class Baza
{
public void Metoda_Baza()
{ … }
public virtual void
Metoda_Comuna() { … }
}
class Derivata: Baza
{
public void Metoda_Derivata()
{ … }
public override void
Metoda_Comuna() { … }
}
Obs.în cazul metodelor virtuale definite în
cadrul claselor de bază și redefinite cu
override în cazul claselor derivate, se va
apela metoda corespunzătoare clasei
obiectului cu care este asignată referin țaîn
momentul execu ției
Baza b = new Derivata();
b.Metoda_Comuna();class Baza
{
public void Metoda_Baza()
{ … }
public virtual void
Metoda_Comuna() { … }
}
class Derivata: Baza
{
public void Metoda_Derivata()
{ … }
public newvoid Metoda_Comuna()
{ … }
}
Obs. utilizarea lui newîn loc de override în
exemplul anterior ar însemna c ǎmetoda din
clasa derivat ǎeste nou ǎ, așa cǎeste
ascuns ǎdacǎeste apelat ǎprin intermediul
unui pointer la clasa de baz ǎ
Baza b = new Derivata();
b.Metoda_Comuna();
Polimorfismul si conversiile de tip
•conversii de la tipul de bază către cel derivat (down -casting )și
invers ( up-casting ).
•conversia de tip de la tipul derivat către bază (up-casting ) este
sigură , simplă și implicită :
Baza b = new Derivata1(); //conversie implicita up -casting
Baza b = new Derivata2();
•conversia de la bază către tipul derivat (down -casting ) nu este
sigură (în sensul că pot apărea excep ții dacă se referă ulterior , de
exemplu, un membru propriu al clasei derivate care nu mai este
accesibil deoarece în urma conversiei obiectul este tratat ca fiind de
tipul de bază )și trebuie realizată explicit; chiar și atunci conversia
poate să nu fie realizabilă , datorită incompatibilită țiiîntre tipuri:
Baza [] b = {new Derivata1(), new Derivata2()};
//corect dar nesigur
Derivata1 d = (Derivata1) b[0];
//exceptie -InvalidCastException
Derivata1 d1 = (Derivata1) b[1];
Operatorii issiaspentru testarea
tipului obiectelor
•verificarea tipurilor utilizind is:
Console.WriteLine (b[0] is Derivata1); //returneaza true
Console.WriteLine (b[1] is Derivata1); //returneaza false
•verificarea tipurilor utilizind as:
Baza [] b = {new Derivata1(), new Derivata2()};
Derivata1 d1 = b[1] as Derivata1;
if (d1 != null)
Console.WriteLine (Conversie de tip corecta!);
else
Console.WriteLine(Conversie de tip incorecta!);
•chiar dacă prezintă o func ționalitate asemănătoare ,isnu face dec ît
să verifice tipul în momentul execu ției pe c îndas,în plus, realizează
și conversia către tipul specificat .
Polimorfism -exemplu
class Program
{
static void Main(string[] args)
{
Punct pt = new Punct(5,7);
Patrat patrat = new Patrat();
Cerc cerc = new Cerc();
Dreptunghi dreptunghi =
new Dreptunghi();
pt.Deseneaza();
// apel metoda deseneaza a clasei Punct
Console.WriteLine("Obiect
din clasa "+pt.IsA);
patrat.Deseneaza();
//apel metoda deseneaza a clasei Patrat
Console.WriteLine("Obiect
din clasa "+patrat.IsA);
dreptunghi.Deseneaza();
//apel metoda deseneaza a clasei Dreptunghi
Console.WriteLine("Obiect
din clasa " + dreptunghi.IsA);cerc.Deseneaza();
//apel metoda deseneaza a clasei Cerc
Console.WriteLine("Obiect
din clasa" + cerc.IsA);
Punct p;
p = new Patrat(8, 3, 20);
p.Deseneaza();
//apel metoda Deseneaza a clasei Patrat
p = new Cerc(7, 10, 40);
p.Deseneaza();
//apel metoda Deseneaza a clasei Cerc
p = new Dreptunghi(2, 7, 30, 50);
p.Deseneaza();
// apel metoda Deseneaza a clasei Dreptunghi
Console.ReadKey();
}
}
Concluzii -polimorfism
•dacǎdorim s ǎredefinim o metod ǎdefinit ǎîntr-o clas ǎde baz ǎca
virtual ǎîn cadrul claselor derivate, aceasta trebuie marcat ǎcu
cuvintele cheie override saunew
•override înseamn ǎcǎmetoda din clasa derivat ǎtrebuie s ǎanuleze
metoda din clasa de baz ǎ, ceea ce conduce la un comportament
polimorfic
•utilizarea lui new în loc de override în exemplul anterior ar însemna
cǎmetoda din clasa derivat ǎeste nou ǎ, așa cǎeste ascuns ǎdacǎ
este apelat ǎprin intermediul unui pointer la clasa de baz ǎ
•obtinerea polimorfismului implica legarea dinamic ǎ(dynamic
binding) care este realizat ǎdoar în faza de execu ție a programului,
și selec ția metodei efectiv apelate se realizeaz ǎpe baza tipului cu
care a fost asignat efectiv obiectul în momentul execu ției
•mecanismul func țiilor virtuale asigur ǎun comportament polimorfic al
metodelor definite virtuale în cadrul unor clase de baz ǎși redefinite
în cadrul claselor derivate cu override, atunci c înd aceste sunt
apelate prin intermediul unor referin țe cǎtre clasa de baz ǎ
Polimorfismul
și colec țiile de obiecte
using System;
using System.Collections.Generic ;
using System.Text ;
namespace FormeGeometrie
{
class MultimeGrafica
{
intnr = 0;
//tabloudeelemente careimplementeaza
//multimea deobiectegrafice
Punct []elemente = new
Punct[20];
public intNr
{
get { return nr; }
}
//adaugaun element multimii
public void Adauga(Punct p)
{
elemente[nr ++] = p;
}//afiseazatoateelementele multimii
public void Afiseaza ()
{
for ( inti=0; i<nr; i++)
elemente[i].Deseneaza ();
}
//element de indexare
public Punct this[int index]
{
get
{
if ((index >= 0)
&& (index <= nr))
return elemente[index ];
else return null;
}
}
}
}
Elemente de indexare
•elementele de indexare sunt
specifice colec țiilordeobiecte și
permit utilizarea mulțimilor de
obiecte ;mulțimile deobiecte potfi
unsetfinitdemembri aiunei
clase, tablouri deobiecte sau
structuri de date complexe
•indiferent dereprezentarea internă
aclasei respective (structura de
date utilizată ),datele potfi
obținute într-o manieră
consistentă prinintermediul
elementelor de indexare
•încazul unui element de indexare
read -only, așacum apare în
exemplul MultimeGrafica ,nu
existǎblocul set•elementul de indexare C#nuare
nume :pentru a-lspecifica seutilizeaz ǎ
cuvîntulcheie this.valoarea indexat ǎ
este accesibil ǎdoar prinindexarea
numelui instan ței.
publicNume_clasa this
[intindex ]
{
get
{
//aici se returneaza o valoare
}
set
{
//aici se seteaza o valoare
}
}
Utilizarea elementelor de indexare (1)
using System;
using System.Collections.Generic ;
using System.Text ;
namespace FormeGeometrie
{
class Program
{
static void Main(string []args)
{
//defineste obiecte din clasele Patrat,
//Cerc si Dreptunghi
Patrat patrat =
new Patrat(8, 3, 20);
Cerc cerc =
new Cerc(7, 10, 40);
Dreptunghi dreptunghi =
new Dreptunghi(2, 7, 30, 50);
//defineste un obiect MultimeGrafica
MultimeGrafica m_gr =
new MultimeGrafica();m_gr.Adauga(patrat);
m_gr.Adauga(cerc);
m_gr.Adauga(dreptunghi);
m_gr.Afiseaza();
//acceseaza pe baza de index elementele
//din cadrul obiectului MultimeGrafica
// definit anterior
for
(int i = 0; i < m_gr.Nr; i++)
{
Console.WriteLine(" X= " +
m_gr[i].X +
" Y= " + m_gr[i ].Y;
m_gr[i].Deseneaza();
}
Console.ReadKey();
}
}
}
Utilizarea elementelor de indexare (2)
•pot exista mai multe elemente de indexare
pentru aceea și structură , func ție de
parametrul furnizat.
•tipurile valide pentru parametri elementelor
de indexare sunt int, string si enum
using System;
using System.Collections.Generic ;
using System.Text ;
namespace MultimeIndexata
{
class MultimeIndex
{
private string[] MultimeObiecte ;
private int DimMultimeObiecte;
public MultimeIndex(int dim)
{
DimMultimeObiecte = dim;
MultimeObiecte = new
string[dim];
for (int i = 0;
i <
DimMultimeObiecte;i++)
{ MultimeObiecte[i] = "VID";
}
}//definire element de indexare cu parametru string
public string this[string dat]
{
get
{
intnr = 0;
for (inti=0;
i<DimMultimeObiecte;i ++)
{
if (MultimeObiecte[i ] ==dat)
nr++;
}
return nr.ToString ();
}
set
{
for (inti=0;
i<DimMultimeObiecte;i ++)
{
if (MultimeObiecte[i ] ==dat)
MultimeObiecte[i ]=value;
}
}
}
Utilizarea elementelor de indexare (3)
//definire element de indexare cu parametru
int
public string this[int
pos]
{
get
{
return
MultimeObiecte[pos];
}
set
{
MultimeObiecte[pos] =
value;
}
}class Program
{
static void Main(string []args)
{
int dim = 10;
MultimeIndex multime =
new MultimeIndex(dim);
//utilizare index intreg
multime[2] = "Al doilea element";
multime[4] = "Al patrulea element";
//utilizare index string
multime["VID"] = "Alte elemente";
//afisare elemente utilizind indexarea
for (int i = 0; i < dim; i++)
Console.WriteLine
("Pozitia " + i +
" = " + multime[i]);
Console.ReadKey();
}
}
}
This
•cuvintul cheie thiseste o variabila locala care apartine
oricarei instante ne -statice a unui obiect si reprezinta o
referin țǎspre obiectul insusi; în consecin ță this are sens
și poate ap ǎrea numai în defini ția unei metode sau
propriet ǎți definite în cadrul unei clase
•this nu necesita declarare si rareori este referit in mod
explicit; el este utilizat in mod implicit pentru referinte
catre membrii obiectului si contine adresa instantei
curente a obiectului respectiv.
•referirea la membri unui obiect prin intermediul lui this
se poate face prin:
this.metoda sau this.proprietatea
Utilizarea colec țiilor .NET Framework –
ArrayList (1)
•ArrayList este unul din tipurile a șa numite de colec ție puse la
dispozi ție de .NET Framework
•constructori:
public ArrayList ()
public ArrayList (ICollection c);
public ArrayList (intcapacity);
•proprietă ți:Capacity, Count, Item , etc.
•metode (parțial):
public virtual intAdd (Object value);
public virtual intBinarySearch (Object value);
public virtual boolContains (Object item);
public virtual boolEquals (Object obj);
public virtual void Remove (Object obj);
Utilizarea colec țiilor .NET Framework –
ArrayList (2)
•colec țiilereprezint ǎelemente extrem
deputernice pentru gestionare
mulțimilor (colec țiilor) deobiecte .
•dezavantajul utiliz ǎrii acestora îl
reprezint ǎfaptul c ǎnu garanteaz ǎ
tipul obiectelor: o colec ție poate
conține mai multe tipuri de obiecte
diferite. Practic, acest lucru permite
stocarea în cadrul unei colec ții a unui
set de obiecte eterogene, maniera de
implementare permi țînd acest lucru: se
poate observa ca majoritatea
metodelor puse la dispozitie de
diversele colec ții implementate în .NET
Framework au ca parametru un obiect
generic de tipul Object;
•în plus, elementele colec țiilor sunt, în
general de tipul Object; din acest
motiv, pentru a se asigura faptul c ǎse
utilizeaz ǎobiecte de un anumit tip dorit
în cadrul aplica ției, se realizeaz ǎ
conversii de tip explicite .•verificarea tipului obiectelor utiliz îndas
•as testeaz ǎși converte ște simultan
tipul referin ței
•returneaz ǎnull dac ǎobiectul nu poate
fi convertit în tipul selectat
switch
(m_elem[i].GetType().ToString ())
{
case " FormeGeometrie.Patrat ":
(m_elem[i ] as
Patrat).Deseneaza (); break;
case " FormeGeometrie.Cerc ":
(m_elem[i ] as
Cerc).Deseneaza (); break;
case
"FormeGeometrie.Dreptunghi ":
(m_elem[i ] as
Dreptunghi).Deseneaza ();
break;
}
Utilizarea colec țiilor .NET Framework –
ArrayList (3)
using System;
using System.Collections.Generic ;
using System.Text ;
namespace FormeGeometrie
{
class Program
{
static void Main(string []args)
{
//defineste obiecte din clasele Patrat, Cerc si Dreptunghi
Patrat patrat = new Patrat(8,3 20);
Cerccerc= new Cerc(7, 10, 40);
Dreptunghi dreptunghi =
new Dreptunghi(2,7,30,50);
//defineste un obiect din clasa ArrayList
System.Collections.ArrayList
m_elem = new
System.Collections.ArrayList ();
//utilizeaza metoda Add a clasei ArrayList
m_elem.Add(patrat);
m_elem.Add(cerc);
m_elem.Add(dreptunghi);//numarul de elemente din colectie (proprietate)
for (int i = 0;
i < m_elem.Count; i++)
{
//GetType() returneaza numele clasei din care //face
parte obiectul; ToString() transforma rezultatul in String
switch
(m_elem[i].GetType().ToString ())
{
case "FormeGeometrie.Patrat":
((Patrat)m_elem[i]).Deseneaza();
break;
case "FormeGeometrie.Cerc":
((Cerc)m_elem[i]).Deseneaza();
break;
case
"FormeGeometrie.Dreptunghi":
((Dreptunghi)m_elem[i]).Deseneaza();
break;
}
}
Console.ReadKey();
}
}
}
Moștenirea șiclasele abstracte
•C#oferǎunmecanism pentru arestric ționa crearea de instan țedinanumite
clase, prinposibilitatea de a defini clase de baz ǎabstracte
•clasele abstracte nupotfiinstan țiate(adicǎnusepotcrea obiecte din
clasa respectiv ǎ; sepot,înschimb , crea referin țecǎtre clase abstracte .
•încercările de a instan țiaoclasǎabstract ǎsunt detectate decompilator și
semnalate cașieroare
•oclasă abstractă furnizează uncadru , unschelet pe baza căruia sepot
construi alteclase, prinderivare; declararea unei clase abstracte seface
adǎugîndcuvîntulcheie abstract
•îndeclara țiaclasei ,clasele abstracte potconținemetode saupropriet ǎți
abstracte ,implementate totprinadǎugarea cuvîntului cheie abstract în
cadrul declara țieiacestora :declara țiaunui membru abstract nueste urmat ǎ
denicio implementare, cuvîntulcheie abstract impun îndcaproprietatea
saumetoda sǎfiedefinit ǎînoricare clasǎderivat ǎ
•dacǎcelpuținunmembru aunei clase este declarat cafiind abstract ,atunci
toatǎclasa trebuie declarat ǎcaabstract ǎ;dacǎînsǎse declar ǎoclasǎ
abstract ǎ,nueste necesar cavre-unul dintre membri acesteia sǎfie
declarat abstract
•pentru a crea o clasǎinstan țiabilǎderivat ǎdintr-oclasǎde baz ǎabstract ǎ,
trebuie redefini țitoțimembri eiabstrac țiîncadrul clasei derivate
Utilizarea claselor abstracte (1)
using System;
using System.Collections.Generic ;
using System.Text ;
namespace Banca_abstracta
{
abstract class Cont_bancar
{
private decimal m_sold ;
private decimal
m_retrageri_totale;
private decimal
m_depuneri_totale;
public decimal Sold
{
get
{ return m_sold ; }
}
public decimal Retrageri_tot
{
get
{
return m_retrageri_totale ;
}
}public decimal Depuneri_tot
{
get
{
return m_depuneri_totale ;
}
}
public abstract string ID
{ get; }
virtual public decimal Depune
(decimal cantitate)
{
m_depuneri_totale += cantitate;
return m_sold +=cantitate ;
}
virtual public decimal Retrage
(decimal cantitate)
{
m_retrageri_totale -= cantitate;
return m_sold -=cantitate ;
}
public abstract string Tiparire ();
}
}
Utilizarea claselor abstracte (2)
//clasaCont_curent
using System;
using System.Collections.Generic ;
using System.Text ;
namespace Banca_abstracta
{
class Cont_curent:Cont_bancar
{
private string m_proprietar ;
public override string ID
{
get
{
return m_proprietar
+ "-contcurent ";
}
}
public Cont_curent
(string proprietar )
{
m_proprietar =proprietar ;
}override public decimal Depune
(decimal cantitate)
{
base.Depune(cantitate);
return Sold;
}
override public decimal Retrage
(decimal cantitate )
{
base.Retrage(cantitate );
return Sold;
}
public override string Tiparire ()
{
return " Tiparire dincontul
curent ";
}
}
}
Utilizarea claselor abstracte (3)
//clasaCont_economii
using System;
using System.Collections.Generic ;
using System.Text ;
namespace Banca_abstracta
{
class Cont_economii:Cont_bancar
{
private string m_proprietar ;
public override string ID
{
get { return m_proprietar
+ "-cont de economii "; }
}
private decimal m_dobinda ;
public decimal Dobinda
{
get { return m_dobinda ; }
set { m_dobinda =value; }
}
•seobserv ǎcǎlaimplementarea membrilor
abstrac țimoștenițiseutilizeaz ǎcuvîntul
cheie override.public Cont_economii
(string proprietar)
{
m_proprietar = proprietar;
}
public decimal Adauga_Dobinda()
{
Depune(m_dobinda*Sold);
return Sold;
}
public override string Tiparire ()
{
return "Tiparire din contul
de economii";
}
}
}
•seobserv ǎutilizarea sintaxei
base.Depune(cantitate) pentru aapela
metoda dinclasa debazǎcare a fost
redefinit ǎînclasa derivat ǎ.Accesul folosind
base poate firealizat dintr-un constructor,
dincadrul unei metode saudincadrul unei
propriet ǎțiaunei instan țeaunui obiect ;într-
ometod ǎstatic ǎaccesul lamembri clasei
debazǎutilizîndbase nueste posibil .
Suprainc arcarea
•Supra încǎrcarea reprezint amecanismul
princare este permis ca, unanumit
operator sauoanumit ametod ǎ(functie)
sapoatafidefinite inmaimulte moduri ,
selec tiafacindu-sefunctiedeargumentele
utilizate
Supra incarcarea metodelor
•înC#,funcțiilesupraincarcate auacela șinume dartrebuie sa
contina o listǎdeparametri diferit ǎ(adica numarul si/sautipul
parametrilor metodelor safiediferit ).
•tipul valorii returnate de o metod ǎsupra încǎrcatǎnureprezint ǎ
factor distinctiv incazul metodelor supraincarcate .
•încazul supraincarcarii codului functiilor ,comportarea codului e
determinata la compilare :functie denumarul si/sautipul
parametrilor utiliza țiînmomentul apelului , se identifica de catre
compilator functia care vafiutilizata , inca dinfaza de compilare.
Acest lucru este diferit sinutrebuie confundat cuutilizarea functiilor
virtuale dincadrul unei ierarhii de clase, in cazul carora
determinarea functiei utilizate efectiv seface doar înmomentul
executiei
•utilizarea metodelor supra încǎrcate simplific ǎinterfa țaclaselor :
astfel ,dacǎavem opera țiisimilare darcare necesit ǎparametri
diferi țiprecum șiimplement ǎridiferite ,utilizarea metodelor
suprîncǎrcate reprezint ǎosoluțieelegant ǎ
Exemplu -clasa Carte
using System;
using
System.Collections.Generic ;
using System.Text ;
namespace Biblioteca
{
class Carte
{
private string m_text ;
private string m_titlu ;
public string Titlu
{
get { return m_titlu ;}
set { m_titlu = value;}
}public string Text
{
get { return m_text ; }
set { m_text = value; }
}
public Carte()
{
}
public Carte(string titlu ,
string text)
{
m_titlu =titlu ;
m_text = text;
}
}
Exemplu -clasa ColectieCarti
class ColectieCarti :
System.Collections.DictionaryBase
{
public void Adauga(Carte book)
{
//apel metoda Add a clasei Dictionary
this.Dictionary.Add(book.Titlu ,
book);
}
public void Extrage(string titlu)
{
//apelmetodaRemove a claseiDictionary
this.Dictionary.Remove(titlu );
}
public boolContine(Carte book)
{
//conversie tipulstringînString
String tit =
(String)book.Titlu ;
//apelmetodaContains a claseiDictionary
return
this.Dictionary.Contains(tit );
}public boolContine(string titlu)
{
String tit = ( String)titlu ;
return this.Dictionary.Contains(tit );
}
//definireelement de indexare
public Carte this[string titlu]
{
get
{
if
(this.Dictionary.Contains(titlu ))
return
(Carte)(this.Dictionary[titlu ]);
else return null;
}
}
}
}
Colectii tipizate
•clasaColectieCarti , este derivat ǎdin clasa de colec ție
DictionaryBase din .NET Framework.
•s-a utilizat aceast ǎabordare pentru a putea utiliza metodele puse la
dispozi ție de clasa DictionaryBase dar și pentru a putea defini astfel
oclasǎde colec ție tipizat ǎ.
•clasele de colec ție generice de tipul ArrayList sunt extrem de
flexibile dar, dup ǎcum a mai fost precizat deja, permit ad ǎugarea
oricǎrui tip de obiecte; dac ǎse dore ște crearea unei colec ții de
obiecte de un anumit tip specific, o abordare relativ simpl ǎeste
aceea de a crea clase de colec țietipizate pe baza claselor de
colec ție abstracte puse la dispozitie de .NET Framework –
System.Collection.Generic .
•colec țiile abstracte sunt puternic tipizate, ce ea ce elimină poten țiale
erori în momentul execu ției. de asemenea, performan ța este mai
bună dec ît ce a colec țiilor generice datorită eliminării conversiilor de
tip.
Clasa DictionaryBase
•furnizeaza oclasa debaza abstracta pentru implementarea
colectiilor puternic tipizate de tip perechi
cheie (key) / valoare (value)
public abstract class DictionaryBase :IDictionary ,
ICollection ,IEnumerable
•metode :
void IDictionary.Add(Object key, Object value);
void IDictionary.Remove(Object key);
bool IDictionary.Contains(Object key);
……
Exemplu -clasa BibliotecaCarti
using System;
using System.Collections.Generic ;
using System.Text ;
namespace Biblioteca
{
class BibliotecaCarti
{
private ColectieCarti m_raft
= new ColectieCarti();
public BibliotecaCarti() { }
public void Intrare
(Carte newBook)
{
m_raft.Adauga(newBook );
}public Carte Iesire(string titlu)
{
Carte theBook =m_raft[titlu ];
m_raft.Extrage(titlu );
return theBook ;
}
//metoda Contine supraincarcata
public boolContine (Carte book)
{
return m_raft.Contine(book );
}
public boolContine (string titlu)
{
return m_raft.Contine(titlu);
}
}
Exemplu –utilizare
static void Main(string []args)
{
BibliotecaCarti m_librarie =
new BibliotecaCarti();
//apel constructorul fara parametri
Carte literatura;
literatura = new Carte();
literatura.Text = "Familia Morometilor
este numeroasa, alcatuita din multi
copii: patru baieti si doua fete";
literatura.Titlu = "Morometii";
Carte tehnica;
tehnica = new Carte();
tehnica.Text = "Clasele sunt blocurile
constructive alprogramelor
orientate peobiecte ";
tehnica.Titlu = "Dezvoltarea
aplicatiilor cu Visual Studio .NET";//apelconstructor cu parametri
Carte dictionar = new Carte
("Dictionar Roman -Englez",
"Dictionarul contine un peste 35000
de cuvinte, expresii");
m_librarie.Intrare(literatura);
m_librarie.Intrare(tehnica);
//apel Contine cu parametru Carte
if (m_librarie.Contine(literatura))
Console.WriteLine("Exista!");
else Console.WriteLine("Nu exista!");
if (m_librarie.Contine(dictionar))
Console.WriteLine("Exista!");
else Console.WriteLine("Nu exista!");
//apel Contine cu parametru string
if
(m_librarie.Contine(literatura.Titlu))
Console.WriteLine("Exista!");
else Console.WriteLine("Nu exista!");
}
Supra încǎrcarea operatorilor
•pentru redefinirea (supra încărcarea ) operatorilor se utilizează numai
metode statice (si publice): operatorii redefini ți astfel apar țin clasei și
nu unei anumite instan țe a acesteia.
•numele operatorilor supraincarcati trebuie săînceapă cu cuv întul
cheie operator , urmat de caracterele reprezent înd operatorul pe
care îl implementează .
•numărul de argumente pe care func țiile care implementează
operatori le pot avea depind de pluralitatea operatorului (unar sau
binar); operatorii binari au întotdeauna doi parametri (nu neaparat
de acela și tip, dar de cele mai multe ori acest lucru se întîmplǎ),în
timp ce cei unari au un singur parametru
•tipul valorii returnate poate fi oricare, însă trebuie ales în func ție de
modalitatea în care se dore ște ca operatorul să poată fi utilizat
Exemplu –clasa Punct (1)
class Puncte
{
private intm_x= 0;
private intm_y= 0;
public intX
{
get { return m_x; }
set { m_x= value; }
}
public intY
{
get { return m_y; }
set { m_y= value; }
}
public Puncte(int x, int y)
{
m_x= x;
m_y= y;
}
public intPatratDistanta ()
{
return (m_x*m_x) + ( m_y*m_y);
}//redefinire operator ==
public static bool operator ==
(Puncte p1,Puncte p2)
{
return ((p1.X == p2.X) &&
(p1.Y == p2.Y));
}
//redefinire operator!= esteobligatorie
public static bool operator !=
(Puncte p1,Puncte p2)
{
return !((p1.X == p2.X) &&
(p1.Y == p2.Y));
}
//redefinire operator binar +
public static Puncte operator +
(Puncte p1,Puncte p2)
{
return new
Puncte(p1.X + p2.X, p1.Y + p2.Y);
}
Exemplu –clasa Punct (2)
//redefinire operator binar-
public static Puncte operator –
(Puncte p1,Puncte p2)
{
return
new Puncte(p1.X -p2.X, p1.Y –
p2.Y);
}
//redefinire operator unar-
public static Puncte operator –
(Puncte p)
{
return new Puncte( -p.X,-p.Y);
}
//supraincarcarea metodelor EqualssiGetHashCode
//nuesteobligatorie daresterecomandata
public override bool Equals(object obj)
{
return (( objisPuncte ) &&
(this == ( Puncte)obj ));
}public override intGetHashCode ()
{
return ( this.X +this.Y );
}
public void Afisare()
{
Console.WriteLine("(" + m_x +
"," + m_y+ ")");
}
}
Observatii :
•inceea ceprive ștesupra încǎrcarea
operatorului ==,dacǎacesta este supra încǎrcat
încadrul unei clase, atunci este obligatorie
supra încǎrcarea și aoperatorului !=(de obicei
redefinirea acestuia se realizeaz ǎpe baza
operatorului ==definit în prealabil).
•acela șilucru este valabil șiîncazul operatorilor
<=respectiv >=
•princonven ție, este recomandat ǎ(darnu
obligatorie )șisupra încǎrcarea metodelor
Equals șiGetHashCode moștenite de la
Object ,acest lucru asigurind o comportare
consistent ǎaobiectelor dinclasa respectiv ǎ
atunci cîndsunt implicate înopera țiide
compara ție
Exemplu –clasa Vector (1)
class Vector
{
private Puncte m_x;
private Puncte m_y;
public Puncte X
{
get { return m_x; }
set { m_x= value; }
}
public Puncte Y
{
get { return m_y; }
set { m_y= value; }
}
public Vector(Puncte x,Puncte y)
{
m_x= x;
m_y= y;
}
//seutilizeaza operatorul ==redefinitpentruPuncte
public static bool operator ==
(Vector v1, Vector v2)
{
return ((v1.X == v2.X) &&
(v1.Y == v2.Y));
}//seutilizeaza operatorul ==redefinitpentruPuncte
public static bool operator ==
(Vector v1, Vector v2)
{
return ((v1.X == v2.X) &&
(v1.Y == v2.Y));
}
//supraincarcarea operatorului != esteobligatorie
public static bool operator !=
(Vector v1, Vector v2)
{
return !((v1.X == v2.X) &&
(v1.Y == v2.Y));
}
//supraincarcarea metodelor EqualssiGetHashCode
/nuesteobligatorie dar esterecomandata
public override bool Equals(object obj)
{
return (( objis Vector) &&
(this == ( Vector)obj ));
}
public override intGetHashCode ()
{
return ( this.X.X *this.Y.X );
}
Exemplu –clasa Vector (2)
//se utilizeaza operatorul + redefinit pentru Puncte
public static Vector operator +
(Vector v1, Vector v2)
{
return new Vector(v1.X + v2.X,
v1.Y + v2.Y);
}
//seutilizeaza operatorul -binarredefinitpentruPuncte
public static Vector operator –
(Vector v1, Vector v2)
{
return new Vector(v1.X -v2.X,
v1.Y -v2.Y);
}
//se utilizeaza operatorul -unar redefinit pentru Puncte
public static Vector operator –
(Vector v)
{
return new Vector( -v.X,-v.Y);
}
public void Afisare ()
{
Console.Write("Vector decoordonate
");
X.Afisare ();Console.Write (" , ");
Y.Afisare ();Console.WriteLine ();
}
}static void Main(string []args)
{
Vector rezultat ;
Puncte p10 = new Puncte(5, 7);
Puncte p1 = new Puncte(14, 17);
Puncte p20 = new Puncte(25,37);
Puncte p2 = new Puncte(12, 54);
Vector v1 = new Vector(p10, p1);
Vector v2 = new Vector(p20, p2);
if (v1 != v2) rezultat = v1 + v2;
else rezultat = v1 -v1;
rezultat.Afisare();
}
Concluzii privind
supraincarcarea operatorilor
•NUtoti operatorii pot fi redefini ti, deoarece aceasta ar conduce la
interac tiuni nedorite cu limbajul C# insusi, printre ace știa
numǎrîndu-se operatorii de atribuire adica = += -=și *=.Operatori
care pot fi redefini ti sunt in principiu urm ǎtorii: + -¡~ ++ –true false
(operatori unari) respectiv + -* / % & | ^ << >> == != > < >= <=
•redefinirea operatorilor este valabil ǎnumai pentru clasele definite de
programator; pentru tipurile standard, operatorii își păstrează
defini ția originală
•nu se permite alegerea pentru operatori a altor simboluri dec ît cele
existente deja
•nu se permite schimbarea pluralită ții operatorului prin redefinire (de
exemplu din unar în binar)
Interfete -definitii ,generalitati (1)
•utilizarea interfe țelorîndezvoltarea aplica țiilorsoftware este
benefică deoarece codul rezultat secaracterizează prin:cuplare
redusă ,programare bazată pe componente ,întreținere ușoară ,
grad ridicat de reutilizare ,datorită decuplării implementării fațăde
interfa ță
•interfe țelereprezintă obiecte (referin țe) dar care undispun denicio
implementare.
•interfe țelesunt asem ǎnǎtoare claselor abstracte care autoțimembri
abstrac ți:încadrul unei interfe țesunt definite metode ,propriet ǎțiși
evenimente pecare oclasǎcare implementeaz ǎinterfa ța
respectiv ǎtrebuie sǎleimplementeze ;însăniciometodă sau
proprietate undispune devre-o implementare încadrul interfe ței.
•interfa țanupoate conținecîmpuri de date
•interfa țaconțineconstructor/ constructori
•defini țiaunei interfe țenupoate conținecuvîntul cheie public :
deoarece scopul interfe țeloreste acela de a defini elementele
(propriet ǎți,metodele ,evenimente , elemente de indexare) asociate
unei clase, nuaresens noțiunea depublic sauprivat înacest
context
Interfete -definitii ,generalitati (2)
•programarea interfe țelor reprezintă o tehnică foarte puternică .
•interfe țele descriu un comportament, e le NU reprezintă capacitate
de stocare pentru date și nici implementare.
•Implementarea interfe țeloreste responsabilitatea claselor care
implementează interfa ța respectivă .
•deoarece interfe țeletrebuie implementate încadrul claselor sau
structurilor derivate , ele potfivăzute cadefinind uncontract prin
care sestipulează obligativitatea unei clase de a implementa
membri respectivi (proprietă ți,metode , etc.).
•înciuda faptului cănuconținniciunfeldefuncționalitate (însensul
de implementare), interfe țelereprezintă structuri deosebit deutile
atunci cîndsedoreștecrearea dearhitecturi software încadrul
cărora implementarea componentelor săpoată firealizată cu
ușurință:atîtatimp cîtcomponentele interșanjabile implementează
aceea șiinterfa ță(care nuseschimbă ),acestea potfiutilizate fără
codsuplimentar
•interfe țelepotfiutilizate pentru a simula moștenirea multiplă ,fără
însăa implica șidezavantajele acesteia
Structura general ǎa unei interfe țe
interface INumeInterfata
{
tip_retur NumeProprietate
{
get;
set;
}
voidNumeMetoda ();
//declarare element de indexareincadrulinterfetei
object this[int index]
{ get;
set;
}
//declaratia unuieveniment incadrulinterfetei
//Test_Eveniment trebuiedeclaratinaintecadelegat
event Test_Eveniment NumeEveniment ;
……
}
Implementarea interfetei
class ClasaInterfata :
INumeInterfata
{// implementare explicita a
// membrilor interfetei
tip_retur NumeProprietate
{
get {..//implementare.. }
set{..//implementare.. }
}
void INumeInterfata.NumeMetoda ()
{
// implementare metoda
…
}
//implementare element de indexare, eveniment,
// etc.
…
}static void Main()
{
// declararea unei instante a interfetei.
INumeInterfata obj =
new ClasaInterfata ();
// apel membru
obj.NumeMetoda ();
…
}
Interfe țeleși moștenirea
interface IParinte
{
void MetodaInterfataParinte();
}
interface ICopil : IParinte
{
void MetodaInterfataCopil();
}
class ClasaInterfata : ICopil
{
public void
MetodaInterfataCopil()
{
Console.WriteLine
("Apel la
MetodaInterfataCopil()");
}public void
MetodaInterfataParinte()
{
Console.WriteLine
("Apel la
MetodaInterfataParinte()");
}
}
static void Main()
{
ClasaInterfata impl =
newICopil ();
impl.MetodaInterfataCopil ();
impl.ParentInterfaceMethod ();
}
Accesul lamembri interfetei
•oclasǎcare implementeaz ǎointerfa țǎtrebuie sǎimplementeze în
mod explicit toțimembri acelei interfe țe
•accesul la membri implementa ți ai interfe ței nu se va realiza prin
intermediul unei instan țe a clasei ci prin intermediul unei referin țe la
interfa ța pe care clasa o implemeneaz ǎ:
INumeInterfata obj= new ClasaInterfata ();
sau
ClasaInterfata impl= new ICopil ();
•secven țeledemaisusimplică polimorfism ,aplicat deaceastă dată
interfe țelor;practic clasa care implementează interfa țaeste oclasă
derivată dininterfa ță
•intruc îtointerfa țănuare un constructor, nusepoate crea unobiect
pebaza unei interfe țedecîtdefinind oclasă derivată dinaceasta ; se
spune “clasa implementează interfa ța.”
•prinintermediul referin țeidefinite se pot accesa doar membri
interfe ței;pentru aaccesa eventualii membri proprii aiclasei care
implementeaz ǎinterfa țatrebuie realizat ǎoconversie explicit ǎa
referin țeicǎtreoreferin țalaclasa respectiv ǎ
Exemplu -interfata IDeplaseaza
using System; //definire interfata IDeplasare
using System.Collections.Generic ;
using System.Text ;
namespace IDeplasare
{//definireenumerare cudirectiile dedeplasare
public enum Directie {Sus,Jos,Stinga ,Dreapta };
//definireproprietati pentrucare sesolicitaimplementare atit pentru getcit si pentru set
public interface IDeplaseaza
{
intX
{
get;
set;
}
intY
{
get;
set;
}
void Deplaseaza(Directie directie ,intcit); //definiremetoda
}
}
Exemplu –implementarea interfetei
class Obiect_deplasat :
IDeplaseaza
{
private intm_x;
private int m_y;
//implementare proprietate X
public intX
{
get { return m_x; }
set { m_x=value;}
}
//implementare proprietate Y
public intY
{
get { return m_y; }
set { m_y=value;}
}//implementare metodamoștenitadininterfata
public void Deplaseaza
(Directie directie ,intcit)
{
switch ( directie )
{
caseDirectie.Sus :m_y-= cit; break;
caseDirectie.Jos :m_y+= cit; break;
caseDirectie.Dreapta :m_x+= cit;
break;
caseDirectie.Stinga :m_x-= cit;
break;
}
}
//implementare metoda proprie clasei
public void Afiseaza()
{
Console.WriteLine("Punct de coordonate(" +
m_x + "," + m_y + ")");
}
}
Exemplu –utilizarea interfetei
class Program
{
static void Main(string[] args)
{
// asignarea unei referin țe la interfata cu o
// referinta la clasa
IDeplaseaza depla =
new Obiect_deplasat();
//acces metoda interfata
depla.X = 10;
depla.Y = 10;
//acces metoda proprie clasei prin intermediul
referinte la interfata necesita conversie explicita
(Obiect_deplasat)depla).Afiseaza();
Console.WriteLine
("Deplasare in sus 5 pozitii");//acces metoda interfata
depla.Deplaseaza(Directie.Sus, 5);
//acces metoda proprie clasei prin intermediul
referintei la interfata necesita conversie
explicita
((Obiect_deplasat)depla).Afiseaza();
}
}
Interfetele simostenirea multipla (1)
//clasaMamifer
class Mamifer
{
protected string specie;
public string Specie
{
get
{
return this.specie ;
}
set
{
this.specie = value;
}
}
}•în C#, spre deosebire de C++, nu
este admis ǎmoștenirea multipl ǎ,
clasele put înd avea o singur ǎ
clasǎde baz ǎ => o limitare majoră
cu impact negativ puternic asupra
scalabilită ții unei aplica ții., prin
intermediul interfe țelor se poate
simula conceptul de mo ștenire
multipl ǎ, clasele C# put înd
implementa mai multe interfe țe
•atunci c înd o clas ǎeste derivat ǎ
dintr-o altǎclasǎși
implementeaz ǎși o interfa țǎ(sau
mai multe), sintaxa definirii clasei
derivate impune ca întîi sǎaparǎ
numele clasei în lista
Interfetele simostenirea multipla (2)
//interfataIInteligenta
interface IInteligenta
{
//declarare metodainterfata
bool
Comportare_inteligenta ();
}
//clasaBalenaderivatadinclasaMamifer
class Balena :Mamifer
{
public Balena ()
{
specie = " Balenele sunt
mamifere ";
Console.WriteLine("{0}",
specie);
}
}//clasaOmderivatadinMamifer
//sicareimplementeaza interfataIInteligenta
class Om: Mamifer, IInteligenta
{
public Om()
{
specie = "Oamenii sunt
mamifere";
}
//definire metoda interfata
public bool
Comportare_inteligenta()
{
Console.WriteLine("{0} si, in
general, prezinta o
comportare inteligenta…",
specie);
return true;
}
Interfetele simostenirea multipla (3)
class Program
{
static void Main(string []args)
{
Balena o_balena =new
Balena ();
Om un_om = new Om();
un_om.Comportare_inteligenta();
Console.ReadLine();
}
}
Obs: Metoda poate fi apelată și prin intermediul
unui obiect de tipul interfe ței:în acest caz
este necesară conversia obiectului către
tipul interfe ței. Această conversie poate fi
realizată corect numai dacă obiectul care se
dorește a fi convertit implementează
interfa ța respectivă (alfel apare o excep ție);
pentru a testa acest lucru se pot utiliza
operatorii isrespectiv as//utilizareis
if (un_omisIInteligenta )
{
//conversie catretipulinterfetei aobiectului un_om
IInteligenta un_om_cu_IQ =
(IInteligenta)un_om ;
un_om_cu_IQ.Comportare_inteligenta ();
}
//utilizareas
IInteligenta un_om_cu_IQ =
un_omasIInteligenta ;
//dacaconversia s-arealizatcusucces
if (null != un_om_cu_IQ )
{
un_om_cu_IQ.Comportare_inteligenta ();
}
Interfe țeMicroSoft .NET Framework
-IComparable (1)
•IComparable -define șteorelațiede
ordonare pemulțimea obiectelor unei
clase
•este utildeutilizat dacǎsedoreștesǎ
sepoatǎrealiza sortarea obiectelor
respective .
•furnizeaz ǎosingur ǎmetod ǎnumit ǎ
CompareTo șicare compar ǎinstan ța
curent ǎaobiectului cuinstan țaprimit ǎ
caparametru obj
class PuncteSortabile:IComparable
{
private int m_x=0;
private int m_y=0;
public intX
{
get { return m_x; }
set { m_x= value; }
}public intY
{
get { return m_y; }
set { m_y= value; }
}
public PuncteSortabile(int x, int y)
{m_x= x;
m_y= y;
}
public intPatratDistanta ()
{
return (m_x*m_x) + (m_y*m_y);
}
//implementarea func ției CompareTo din cadrul interfetei
public intCompareTo(object obj)
{
return this.PatratDistanta ()-
((PuncteSortabile)obj ).PatratDistanta ();
}
}
Interfe țeMicroSoft .NET Framework
-IComparable (2)
private void button1_Click
(object sender, EventArgs e)
{
ArrayList puncte = new
ArrayList ();
//generator numerealeatoare
Random rgen= new Random();
PuncteSortabile punct;
Graphics graph =
this.CreateGraphics ();
//inserararea intabelulpunctea 100 depuncte
//generate aleator
for (inti = 0; i < 100; i++)
puncte.Add(new
PuncteSortabile(rgen.Next(200),
rgen.Next(200)));//sortaretabloupuncte –foloseste IComparable.CompareTo
puncte.Sort ();
//desenare puncte sortate
for (int i = 0; i < 100; i++)
{
punct =
(PuncteSortabile)puncte[i];
Color color =
System.Drawing.Color.FromArgb(67, 43, i);
System.Drawing.SolidBrush brush =
newSystem.Drawing.SolidBrush(color );
graph.FillEllipse(brush ,punct.X ,
punct.Y , 10, 10);
brush.Dispose ();
}
}
Interfe țeMicroSoft .NET Framework
-IEnumerable șiIEnumerator
•asigur ǎsuport pentru aputea realiza enumer ǎriprintre obiectele unei
clase utilizîndforeach .
•încazul încare se doreșteimplementarea unei clase de tip colec ție
pecare sǎsepoatǎrealiza enumer ǎricuajutorul luiforeach ,aceast ǎ
clasǎtrebuie sǎfieenumerabil ǎ=>clasa colec țierespectiv ǎtrebuie
sǎimplementeze interfa țaIEnumerable și,înconsecin țǎ,sǎ
implementeze metoda GetEnumerator ainterfe țeiIEnumerable
•metoda GetEnumerator returneaz ǎoinstan țǎIEnumerator ,deci
este absolut necesar sǎsedefineasc ǎoaltǎclasǎcare sǎ
implementeze clasa IEnumerator ;aceast ǎclasǎvafiutilizat ǎdoar de
metoda GetEnumerator pentru arealiza enumerarea ,deci, deobicei
clasa este imbricat ǎîncadrul clasei colec țieenumerabil ǎ
•clasa ListaPuncteSortate este clasa colec țiecare vrem sǎfie
enumerabil ǎ,deci implementeaz ǎIEnumerable iarclasa
EnumeratorPuncte este oclasǎdefinit ǎîninteriorul acesteia (clasǎ
intern ǎ) care implementeaz ǎenumeratorul propriu -zis,deci
implementeaz ǎIEnumerator .Clasa EnumeratorPuncte trebuie s ǎ
implementeze metodele Reset, MoveNext și proprietatea Current ale
clasei IEnumerator
Exemplu -ListaPuncteSortate
enumerabila (1)
namespace Deseneaza_Puncte
{
class ListaPuncteSortate:IEnumerable
{
//tabloulprincareimplementeaza colectia
enumerabila
ArrayList m_PuncteEnumerabile
= new ArrayList ();
//clasainternacareimplementeaza enumeratorul
private class EnumeratorPuncte :
IEnumerator
{
ArrayList m_puncte ;
intm_pozitie =-1;
intm_nr;
//constructor
public EnumeratorPuncte
(ArrayList puncte )
{
m_puncte =puncte ;
m_nr=puncte.Count ;
}//implementarea metodeiReset
public void Reset()
{
m_pozitie =-1;
}
//implementarea metodeiMoveNext
public boolMoveNext ()
{
if (m_nr==m_puncte.Count )
{
m_pozitie ++;
if (m_pozitie >=m_puncte.Count )
return false;
else return true;
}
else
{
throw new InvalidOperationException
("Colectia s-aschimbat intimpul
enumerarii !");
}
return true;
}
Exemplu -ListaPuncteSortate
enumerabila (2)
//implementarea proprietatii Current
public object Current
{
get
{
if (m_nr!=m_puncte.Count )
throw new
InvalidOperationException
("Colectia s-aschimbat
intimpul
enumerarii !");
else
if (m_pozitie >=m_puncte.Count )
throw new
InvalidOperationException
("Valoare curenta incorecta !");
else return m_puncte[m_pozitie ];
}
}
}
Obs.enumerarea unei colec țiidefinite ca maisus
eșueaz ǎîncazul încare colec țiasemodific ǎîn
timpul enumer ǎrii: din acest motiv ,însitua ția
respectiv ǎsegenereaz ǎoexcep țieutilizînd
throwpublic void AdaugaPuncteEnumerabile
(intn)
{
m_PuncteEnumerabile.Clear ();
Random rgen= new Random();
//inserararea in tabel a punctelor generate aleator
for (int i = 0; i < n; i++)
m_PuncteEnumerabile.Add
new PuncteSortabile
(rgen.Next(200),
rgen.Next(200)));
//sortare tablou puncte
m_PuncteEnumerabile.Sort();
}
//implementarea metodei GetEnumerator
public IEnumerator GetEnumerator()
{
return new
EnumeratorPuncte(m_PuncteEnumerabile );
}
}
}
Exemplu -ListaPuncteSortate
enumerabila (3)
Obs.Inițializarea colec țieienumerabile afostrealizat ǎprinintermediul unei funcțiiproprii
AdaugaPuncteEnumerabile aclasei ListaPuncteSortate .
private void button1_Click(object sender, EventArgs e)
{
ListaPuncteSortate puncte_enumerabile = new ListaPuncteSortate ();
puncte_enumerabile.AdaugaPuncteEnumerabile(100);
Graphics graph = this.CreateGraphics();
//desenare puncte sortate: intrucit nu se mai utilizeaza fo r va trebui
//incrementat explicit contorul in cadrul enumerarii
int i = 1;
foreach
(PuncteSortabile punct in puncte_enumerabile)
{
Color color = System.Drawing.Color.FromArgb(67, 43, i++);
System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(color );
graph.FillEllipse(brush ,punct.X ,punct.Y , 10, 10);
brush.Dispose ();
}
}
Alte interfe țe.NET Framework
•IFormatable –permite definirea deșirurideformatare personalizate
•ICollection -asigură acces laelementele colec țieiprinintermediului unui
enumerator .Practic ,toate clasele care implementează colec țiide date în
.NET implementează ICollection :Array ,ArrayList ,BitArray ,Queue ,Stack ,
HashTable ,SortedList ,StringDictionary ,ListDictionary ,
NameValueCollection
•IList –oferă acces direct ladatele unei colec țiiprinaccesarea articolelor
utilizîndunindex ; clase de uzgeneral care implementează IList sunt Array (
reprezintă untablou dedimensiune fixată ),ArrayList (reprezintă untablou a
cărui dimensiune creștedinamic înfuncțiedenecesită ți)șiStringCollection
(care reprezintă untablou dimensionat dinamic specific pentru siruri ). Un alt
exempu de utilizare pentru IList arfiacela căunobiect detipul IList poate
constitui sursǎde date pentru controale Windows de tipListBox sau
DataGrid
•IDictionary –asigură acces la un enumerator care implementează
IDictionaryEnumerator oferind astfel acces laperechi detipul nume /valoare .
Clase care implementează interfa țaIDictionary sunt:HashTable ,SortedList ,
StringDictionary ,ListDictionary ,NameValueCollection
•ICloneable –permite specificarea modalit ǎțiiîn care va fi copiat un tablou
Clase generice
•utilizarea tipurilor (claselor) parametrizate saugenerice în C#
conduce la reducerea duplicării func țiilor precum și a claselor cu
implementări similare , dar care diferă prin tipul argumentelor sau a
datelor utilizate.
•o definiție generica furnizează doar formatul general al clasei sau
metodei definite astfel, T, T1,…etc. fiind tipurile generice p e care
compilatorul le va înlocuiîn momentul apelului, func ție de tipurile
parametrilor actuali transmi și.
•claseleși metodele generice combina reutilizarea, siguran ța
tipurilorși eficiențaîntr-o maniera nu întotdeauna posibil claselor
non-generice
•utilizatorul poate, de asemenea, sa -și defineasca propriile clase și
metode generice
Colectiigenerice (1)
•problema care rezultă în urma utilizării colec țiilor de tipul
ArrayList este că acestea operează pe baza tipului object .
Deoarece toate obiectele derivă din tipul object => se pot
introduce în cadrul unei colec ții de tipul ArrayList orice tip de
elemente
•o consecin ță a acestui fapt : conversii de tip necesare cu implica ții
asupra performan țeiși asupra fiabilită ții soluției (erori la execu ție)
•o colecție generică este puternic tipizată (sigură din puctul de
vedere al tipului) => e limină poten țialele erori la execu ție
•spațiul de nume System.CollectionGeneric definește colecții
generice
Colectiigenerice (2)
System.CollectionGeneric –clase, interfete, etc.
•public class Dictionary<TKey, TValue> reprezintă o colec ție de
perechi chei/valoare
•public class List<T> reprezintă o listă puternic tipizată de obiecte
care pot fi accesate prin index
•public class LinkedList<T> reprezintă o listă dublu înlănțuită
•public class SortedList<TKey, TValue> o colecție de perechi
chei/valoare sortate pe baza cheii utilizind implementarea pentr u
IComparer<T> asociat
•public interface IComparer<T > definește o metodă care este
utioizată pentru a compara două obiecte
•public class HashSet<T> furnizează o colec ție de elemente pe
care sunt implementate opera ții foarte perfomante
O lista generica (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace ListaGenerica
{
class ListaGen<T>
{
// clasa generica pentru definirea structurii de
Nod
private class Nod
{
// constructor
public Nod(T t)
{
next = null;
data = t;
}
private Nod next;public Nod Next
{
get return next; }
set { next = value; }
}
// cimpul de date data este privat si de tipul T
private T data;
// proprietatea Data returneaza un tip generic T
public T Data
{
get { return data; }
set { data = value;
}
}
}
private Nod inceput;
// constructor
public ListaGen()
{
inceput = null;
}
O lista generica ( 2 )
// functie generica cu parametru de tipul T
public void Insereaza(T
t)
{
Nod n = new Nod(t);
n.Next = inceput;
inceput = n;
}//implementarea metodei GetEnumerator()
// pentru a
//putearealiza iteratii utilizind foreach
public IEnumerator<T>
GetEnumerator()
{
Nod current = inceput;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
}
O lista generica ( 3 )
static void Main(string[] args)
{
Console.WriteLine
("Lista de numere intregi
int");
// lista numere intregi int
ListaGen<int> lista_intregi =
new ListaGen<int>();
for (int x = 0; x < 10; x++)
{
lista_intregi.Insereaza(x);
}
foreach (int i in
lista_intregi)
{
Console.Write(i + " ");
}Console.WriteLine();
Console.WriteLine
("Lista de siruri string");
// lista siruri de caractere
ListaGen<string> lista_siruri =
new ListaGen<string>();
for (int x = 0; x < 10; x++)
{
lista_siruri.Insereaza(
"("+x.ToString()+")");
}
foreach (string i in
lista_siruri)
{
Console.Write(i + " ");
}
Console.WriteLine();
}
Serializarea
•termenul de serializare se foloseșteîn limbajele orientate pe
obiecteîn legătură cu persisten ța obiectelor (instanțelor); pen tru
ca un obiect să fie persistent , el trebuie salvat pe o memorie
nevolatilă pentru a putea fi restaurat ulterior pe baza informa țiilor
salvate.
•datele instan ței serializate sunt salvate în ordine, de obicei c împ cu
cîmp; daca se dore ște serializarea mai multor instan țe, salvarea
datelor acestora se realizeaza în ordine, una dupa alta
•serializarea se face secven țial, deci ordinea de salvare trebuie să fie
aceeași cu ordinea de citire pentru restaurare. Nu se pot accesa
înregistrări individuale , deci serializarea nu se poate folosi pentru
stocarea bazelor de date
•deserializarea reprezinta opera ția inversa serializarii prin care
datele serializate în prealabil sunt inserate într-o instanța (sauîn
instanțe) ale clasei
Moduri de serializare
•se pot utiliza diferite standarde, dintre care cele mai cunoscut e
standarde de industrie sunt fișierele bitmap (serializare binara) și
fișierele XML (Extensible Markup Language)
•NET Framework pune la dispozitie clase specifice pentru opera țiile
de serializare/deserializare: BinaryFormatter pentru serializarea
binarǎrespectiv XMLSerialization pentru seriaizarea XML
•pentru serializarea binar ǎtrebuie ad ǎugat atributul Serializable în
fiecare clas ǎcare se dore ște a fi serializat ǎ
•atributulSerializable nu este mo ștenit, ceea ce înseamnă că ,în
cazulîn care o clasă este marcată ca serializabilă , clasele derivate
din acestea nu pot fi automat serializate: a cest lucru este logic
deoarece aceste clase ar putea avea membri care nu sunt
serializați.
•pentru a marca faptul că un anumit c împ nu este serializabil, se
poate utiliza atributul NonSerializable ; spre deosebire de
Serializable, atributul NonSerializable este însă moștenit
Interfata ISerializable
•daca se dore ște definirea c împurilor de serializat precum și controla
modul de serializare în locul serializarii predefinite, se poate
implementa interfa țaISerializable .A stfel, se poate defini o
metoda de serializare proprie redefinind singurul membru al
interfețeiISerializable, și anume metoda GetObjectData. Primul
parametru al acestei metode, de tip SerializationInfo reprezint ǎo
colecție de tip nume/valoare care va fi transferat ǎprocesului de
serializare; practic , va fi serializata doar informa ția adaugata în
instanțaSerializationInfo .
•pentru deserializare, trebuie definit un constructor care prime ște
aceiași parametri ca șiGetObjectData și care va fi utilizat în
procesul de deserializare, la crearea instan țelor obiectelor
O clasa serializabila (1)
namespace SerializareDate
{
//ad ǎugare atribut Serializable
[Serializable()]
public class Persoana:
System.Runtime.Serialization.
ISerializable
{
string m_nume;
string m_prenume;
int m_virsta;
public string Nume
{
get { return m_nume; }
set { m_nume = value; }
}public string Prenume
{
get { return m_prenume; }
set { m_prenume = value; }
}
public int Virsta
{
get { return m_virsta; }
set { m_virsta = value; }
}
public Persoana
(string n, string p, int v)
{
m_nume = n;
m_prenume = p;
m_virsta = v;
}
O clasa serializabila (2)
//constructor f ǎrǎparametri
public Persoana()
{
}
//constructor pentru deserializare
public Persoana(System.Runtime.
Serialization.SerializationInfo
info,
System.Runtime.Serialization.
StreamingContext context)
{
m_nume =
info.GetString("Nume");
m_prenume =
info.GetString("Prenume");
m_virsta =
info.GetInt32("Virsta");
}//implementarea metodei GetObjectData a interfe ței
ISerializable
public void
GetObjectData(System.Runtime.
Serialization.SerializationInfo info,
System.Runtime.Serialization.
StreamingContext context)
{
info.AddValue("Nume", m_nume);
info.AddValue("Prenume", m_prenume);
info.AddValue("Virsta", m_virsta);
}
public void Afisare()
{
Console.Write(" Nume = "+m_nume);
Console.Write(" Prenume =
"+m_prenume);
Console.WriteLine(" Virsta =
"+m_virsta);
}
}
O colectie serializabila
namespace SerializareDate
{
//ad ǎugare atribut Serializable
[Serializable()]
public class
ColectieSerializabila:
System.Collections.CollectionBase
{
public
ColectieSerializabila()
{
}
public void Adauga(Persoana p)
{
this.InnerList.Add(p);
}
public void Sterge(Persoana p)
{
this.InnerList.Remove(p);
}public void Afisare()
{
foreach (Persoana p in
this.InnerList)
p.Afisare();
}
public void Add(Persoana p)
{
this.InnerList.Add(p);
}
public Persoana this[int index]
{
get
{return (Persoana)
(this.List[index]);}
set
{ this.List[index] = value; }
}
}
}
Serializarea binara (1)
•instanțele sunt memorate sub forma unui flux de octe ți care
conțineîntregul obiect adic ǎtoate cîmpurile publice sau
private ale instan ței.
•în procesul de serializare binara se implementeaz ǎinterfața
ISerializable ; datele serializate în format binar nu pot fi citite
sub formǎde textînsǎnu sunt nici criptate
Serializarea binara (2)
using System;
using System.Collections.Generic;
using System.Text;
//pentru utilizarea clasei BinaryFormatter
using System.Runtime.Serialization.
Formatters.Binary;
namespace SerializareDate
{
class Program
{
static void Main(string[] args)
{
ColectieSerializabila m_persoane
= new ColectieSerializabila();
//serializare binara
string m_fisierBinar =
"persoane.dat";
Persoana pers_01 = new
Persoana("Zmaranda", "Doina",
40);
m_persoane.Adauga(pers_01);Persoana pers_02 = new
Persoana("Rusu", "Claudia", 25);
m_persoane.Adauga(pers_02);
Persoana pers_03 = new
Persoana("Gligor", "Marius", 27);
m_persoane.Adauga(pers_03);
//afisare continut m_persoane inainte de serializare
m_persoane.Afisare();
//serializarea informatiilor continute in m_persoane
//in format binar
System.IO.Stream stream = new
System.IO.FileStream(m_fisierBinar,
System.IO.FileMode.Create);
BinaryFormatter ser_binar = new
BinaryFormatter();
ser_binar.Serialize(stream,
m_persoane);
stream.Close();
Serializarea binara (3)
//golire continut m_persoane in vederea
// deserializarii
m_persoane.Clear();
//deserializarea informatiilor continute
// in m_persoane
System.IO.Stream alt_stream = new
System.IO.FileStream(m_fisierBinar,
System.IO.FileMode.Open);
BinaryFormatter des_binar = new
BinaryFormatter();
m_persoane = (ColectieSerializabila)
des_binar.Deserialize(alt_stream);
stream.Close();
m_persoane.Afisare();
}
}
}Obs.Metoda Serialize a obiectului
BinaryFormatter primește ca
parametri fluxul de serializare
precumși obiectul care se dore ște a
fi serializat. Metoda Deserialize a
obiectului prime ște ca parametru o
instanțǎFileStream și returneaz ǎo
instanțǎSystem.Object. Din acest
motiv trebuie realizat ǎo conversie
explicitǎde tip cǎtre tipul ini țial,
anterior serializ ǎrii
(ColectieSerializabila).
Limbajul XML (1)
(Extensible Markup Language)
•prima varianta a limbajului XML (XML 1.0) a ap ǎrutîn
1998
•este un limbaj de marcare, asem ǎnǎtor HTML -ului dar
care difer ǎfața de acesta prin urm ǎtoarele:
–HTML reprezint ǎdoar o tehnologie de prezentare; practic, codul
HTML nu relev ǎabsolut nimic despre informa ția asupra c ǎreia
tag-urile HTML sunt aplicate.
–numele de tag -uri HTML nu indic ǎnimic referitor la con ținutul la
care se refer ǎci doar la modul în care contintul va fi afi șat
(aspectul s ǎu)
–HTML are un set fix de tag -uri predefinite, care nu poate fi
extins de c ǎtre utilizator
Limbajul XML (2)
(Extensible Markup Language)
•documentele XML reprezint ǎde fapt colec ții de date și constǎ
dintr-o ierarhie imbricat ǎde elemente av înd o singur ǎrǎdǎcinǎ;
•fișierele XML se autodescriu: tag -urile descriu at ît structura c îtși
tipul datelor pe care le con țin
•limbajul XML este extensibil în sensul c ǎpermite utilizatorului s ǎ-și
defineasc ǎpropriile tag -uri
•fișierele XML sunt portabile (se bazeaz ǎpe Unicode)
•fișierele XML descriu datele sub form ǎde arbori și/sau grafuri
•documentele XML sunt destinate în primul r înd descrierii și
structurǎrii datelor
•XML nu trebuie v ǎzut ca un înlocuitor al HTML -ului deoarece cele
douǎlimbaje sunt destinate unor scopuri complet diferite:
–XML este destinat descrierii și structurǎrii datelor și este orientat pe
conținutul datelor
–HTML este destinat afi șarii datelor și este orientat pe modul cum
acestea sunt vizualizate.
Structura documentelor XML (1)
<?xml version="1.0"
encoding="ISO -8859-1"?>
<nota>
<catre>Radu</catre>
<dela>Ioana</dela>
<antet>Atentie</antet>
<body>
Nu uita tema la matematica!
</body>
</nota>
<radacina>
<copil>
<subcopil>…..</subcopil>
</copil>
</radacina>•sintaxa este auto -descriptiv ǎ:
prima linie con ține declara ția
XML care define ște de obicei
versiunea XML utilizat ǎ
•linia urmǎtoare descrie elementul
rǎdǎcinǎ(root) al documentului
(<nota>)
•restul elementelor sunt
elementele “copii”ale rǎdǎcinii:
<catre>, <dela>, <antet> și
<body>.
•imbricarea elementelor poate
continua pe mai multe niveluri:
elementele “copii”pot fi la rîndul
lor elemente r ǎdǎcinǎpentru alte
elemente “sub-copii”
Structura documentelor XML (2)
•toate documentele XML trebuie sa aibă tag -uri atît deînceput
cîtși de sfirșit, spre deosebire de HTML unde există anumite
elemente pentru care tag -ul de sfîrșit nu este obligatoriu
•elementele XML sunt case-sensitive, spre deosebire de HTML
•elementele XML trebuie să fie încuibate corespunzător
•toate documentele XML trebuie să aibă un element rădăcină
(root)
•asemănător cu HTML , tag-urile pot avea și atribute, care
trebuieîntotdeuna să apară între ghilimele
•spațiile din documentele XML sunt luate în considerare; CR/LF
este convertit în LF
•comentariile în XML sunt similare celor din HTML <! –->
Atribute
•elementele XML pot
formate at ît dintr-un
conținut cîtși din
attribute.
•atributele adaugă
informații suplimentare
elementelor XML.
•valoarea atributelor
XML trebuie
întotdeauna inclusă
între ghilimele<librarie>
<carte categorie="BELETRISTICA">
<titlu limba="en">Gone with the
wind</titlu>
<autor>Margaret Mitchell</autor>
<an>2001</an>
<pret>30.00</pret>
</carte>
<carte categorie="COPII">
<titlu limba="ro">Pinochio</titlu>
<autor>Carlo Collodi</autor>
<an>2003</an>
<pret>25.00</pret>
</carte>
<carte categorie="CALCULATOARE">
<titlu limba="ro"> XML</titlu>
<autor>Lee Ann Phillips</autor>
<an>2000</an>
<pret>40.00</pret>
</carte>
</librarie>
Atribute
Element root
<librarie>
Element
<carte >Atribut
“categorie”
Element
<titlu >Element
<autor >Element
<an>Element
<pret>Atribut
“lang”
Atribute versus elemente in XML
<persoana sex= ”masculin ”>
<nume>Popescu</nume>
<prenume>Ion</prenume>
</persoana>
<persoana>
<sex>masculin<sex>
<nume>Popescu</nume>
<prenume>Ion</prenume>
</persoana>
•în XML este de obicei recomandată evitarea atributelor pe c ît posibilși
utilizarea în locul acestora a elementelor XML, în primul r înd datorită unor
limitări ale atributelor fa ța de elemente:
–atributele nu pot con ține valori multiple, elementele pot
–atributele nu pot con ține structuri, elementele pot
–atributele nu sunt extensibile pentru schimbări ulterioare
–=>pentru memorarea datelor este de preferat să se utilizeze elemen te;
atributele se pot utiliza atunci c înd informa ția conținutăîn ele un este
relevantă pentru date
Concluzii -XML
•un document XML reprezintă un fi șier text, care con ține tag-uri definite
dar careîn sine, nu face nimic;
•un astfel de document va fi utilizat însă de o aplica ție careștie să lucreze
cu XML care va ști să trateze corespunzător fiecare tag din cadrul fi șierului
XML, func ție de cerin țele specifice ale aplica ției
•XML oferǎsuport pentru stocarea informa ților dar,în special pentru a
transmite și interschimba date între diferite tipuri de platforme
•în prezent, majoritatea browser -elor includ suport pentru XML
•în particular, limbajul C# include suport pentru documenta țieîn format
XML:
///<summary>
///text comentariu pentru documentatie
///</summary>
•eticheta <summary> face parte dintr -o serie de etichete pentru
comentarii acceptate în C#și .NET Framework.;pe baza acestor comentarii
incluseîn fișierul sursǎC# se poate genera automat un fi șier de
documenta țieîn format XML.
Validarea și corectitudinea
documentelor XML
•există o diferen ță semnificativă vizavi de ceea ce înseamnă un
document XML corect sau valid
•un document XML se consideră a fi corect dacă el se conformează
regulilor de sintaxă XML
•un document XML este valid dacă acesta se conformează regulilor
definiteîn cadrul unui DTD ( Document Type Definition ) impuse
pentru structura documentului în cauză
•referă un fi șier .dtd extern care define ște structura pe care
documentul XML trebuie să o aibe
<?xml version="1.0" encoding="ISO -8859-1"?>
<!DOCTYPE nota SYSTEM “nota.dtd ”>
<nota>
<catre>Radu</catre>
<dela>Ioana</dela>
<antet>Atentie</antet>
<body>Nu uita tema la matematica!</body>
</nota>
Utilizarea DTD -urilor
pentru validarea documentelor XML
<!DOCTYPE nota [
<!ELEMENT nota (catre, dela, antet, body)>
<!ELEMENT catre (#PCDATA)>
<!ELEMENT dela (#PCDATA)>
<!ELEMENT antet (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
•linia!DOCTYPE nota definește că acesta este un document
de tipnota
•!ELEMENT nota definește elementul notaca avînd 4
sub-elemente (elemente copil): "catre,dela,antet,body"
•!ELEMENT to (in linia 4) define ște elementul toca fiind de
"#PCDATA"
•!ELEMENT catre definește elementul catreca fiind de tipul
PCDATA…
Avantajele utiliz ării DTD-urilor
(Document Type Definition)
•Parsed Character Data (PCDATA) se re feră la textul
care se găse șteîntre tag-ul de sfîrșitși cel deînceput al
unui element XML și care va fi interpretat(parsed) .
•Character Data (CDATA), text de tip sir de caractere
care nu va fi interpretat.
•utilizarea DTD -urilor este necesară deoarece :
–utilizînd DTD-uri, fiecare document XML dispune de o
descriere a formatului acestuia
–folosind acela și DTD, rezultă fi șiere XML cu structuri
identice, care pot fi utilizate pentru schimbul de informa ție
–utilizînd DTD-uri standard, se poate verifica daca datele
utilizate de fi șierul XML sunt valide
Structura DTD -urilor
•din punctul de vedere al DTD -urilor, documentele
XML pot fi construite din următoarele blocuri :
–elemente : reprezintă structura cea mai complexă ,
putînd conține alte elemente, t ext sau să fie vide
–tag-uri: utilizate pentru marcarea elementelor
(la inceput și sfîrșit)
–atribute: conțin informa ții suplimentare despre
elemente
–entități: sunt variabile utilizate pentru a defini
porțiuni utilizate în comun de text. Există predefinite
în XML următoarele entită ți: < (<),< (>),&
(&)," ("),' (');
Utilizarea schemelor XML
pentru validarea documentelor XML
•reprezintă o alternativă la validarea bazată pe DTD este constit uită din a șa numita
schemă XML
<?xml version="1.0"?>
<xs:schema
<xs:element name="nota">
<xs:complexType>
<xs:sequence>
<xs:element name="catre"
type="xs:string"/>
<xs:element name="dela"
type="xs:string"/>
<xs:element name="antet"
type="xs:string"/>
<xs:element name="body"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Structura schemelor XML (1)
•elementul <schema> este elementul rădăcină a oricărei scheme XML ,
aastfelîncît forma generală a unei scheme XML va fi următoarea :
<?xml version="1.0"?>
<xs:schema>
…
</xs:schema>
•o schemă XML poate con ține elemente simple, de forma:
<xs:element name="xxx" type="yyy"/>
•tipurile posibile într-o schemă XML sunt următoarele : xs:string,
xs:decimal, xs:integer , xs:boolean, xs:date, xs:time:
<xs:element name="nume" type="xs:string"/>
<xs:element name="virsta" type="xs:integer"/>
<xs:element name="datanasterii" type="xs:date"/>
Structura schemelor XML (2)
•un element complex poate con ține atribute, alte elemente și
text
•Indicatorul sequence specifică faptul că elementele trebuie să
aparăîn secvența (ordinea) da tă
<xs:element name="aviz">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="numefirma"
type="xs:string"/>
<xs:element name="numarfactura"
type="xs:positiveInteger"/>
<xs:element name="datafactura"
type="xs:date"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Serializarea XML
•spre deosebire de serializarea binar ǎ,în XML sunt serializabile
doar cîmpurileși propriet ǎțile publice dac ǎdatele instan țelor
nu sunt accesibile din c împurile sau propriet ǎțile publice, ele
nu vor fi ini țializate la deserializarea obiectelor
•pentru serializarea XML este necesar un constructor public,
fǎrǎparametri
–pentru a serializa o clas ǎcare implementeaz ǎICollection, cum este clasa
ColectieSerializabila care are ca și clasǎde bazǎCollectionBase, trebuie
implementa ți urmǎtorii membri:
–metoda Add cu un parametru de acela și tip cu obiectul returnat de
proprietatea Current a metodei GetEnumerator; metoda Add din cad rul clasei
ColectieSerializabila este acceptabil ǎdin acest punct de vedere
–un element de indexare care s ǎreturneze acela și tip cu metoda Add definit ǎ
anterior; un astfel de element de indexare a fost definit în cadrul colec ției
ColectieSerializabila
–acești membri permit procesului de serializare s ǎacceseze obiectele colec ției
prin intermediul elementului de indexare și sǎdeserializeze obiectele prin
metoda Add
Serializarea XML (1)
using System;
using System.Collections.Generic;
using System.Text;
//pentru utilizarea clasei XMLSerializer
using System.Xml.Serialization;
namespace SerializareDate
{
class Program
{
static void Main(string[] args)
{
ColectieSerializabila m_persoane = new ColectieSerializabila() ;
//serializare XML
string m_fisierXML = "persoane.xml";
Persoana pers_01 = new Persoana("Zmaranda", "Doina", 40);
m_persoane.Add(pers_01);
Persoana pers_02 = new Persoana("Rusu", "Claudia", 25);
m_persoane.Add(pers_02);
Persoana pers_03 = new Persoana("Gligor", "Marius", 27);
m_persoane.Add(pers_03);
Serializarea XML (2)
//afisare continut m_persoane inainte de serializare
m_persoane.Afisare();
//asociere obiect writer cu fisierul
System.IO.TextWriter writer = new System.IO.StreamWriter(m_fisi erXML);
//creare obiect xmlSerial cu parametru tipul obiectelor seri alizate
XmlSerializer xmlSerial = new
XmlSerializer(typeof(ColectieSerializabila));
//apel metoda de serializare
xmlSerial.Serialize(writer, m_persoane);
writer.Close();
//deserializare xml
System.IO.TextReader reader = new System.IO.StreamReader(m_fisi erXML);
XmlSerializer xmlDeserial = new
XmlSerializer(typeof(ColectieSerializabila));
// metoda Deserialize returneaz ǎo instan țǎSystem.Object
m_persoane = (ColectieSerializabila)xmlDeserial.Deserialize(rea der);
reader.Close();
}
} }
Rezultatul serializarii XML
<?xml version="1.0" encoding="utf -8"?>
<ArrayOfPersoana
xmlns:xsi="http://www.w3.org/2001 /XMLSchema -instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Persoana>
<Nume>Zmaranda</Nume>
<Prenume>Doina</Prenume>
<Virsta>40</Virsta>
</Persoana>
<Persoana>
<Nume>Rusu</Nume>
<Prenume>Claudia</Prenume>
<Virsta>25</Virsta>
</Persoana>
<Persoana>
<Nume>Gligor</Nume>
<Prenume>Marius</Prenume>
<Virsta>27</Virsta>
</Persoana>
</ArrayOfPersoana>
Exceptii in C# (1)
•mecanismul tratării excep țiilor permite managerizarea
într-o manieră ordonată a erorilor din timpul execu ției.
•la apariția unei erori, programul poate invoca automat
o rutină de tratare a acesteia
•avantajul principal al tratării excep țiilor este faptul că
automatizează codul de tratare a erorilor
•tratarea excep țiilor este binevenită mai ales când
eroarea apare la un nivel îndepărtat ,într-un set de
rutineîncuibate pe multe niveluri
•în C# erorile generate la execu ția programului sunt
propagate utiliz înd mecanismul excep țiilor
Exceptii in C# (2)
•la apelul unei func țiiîn timpul execu ției unui program, execu ția funcției poate
fi: normală, cu erori sau anormală .
•la execuția normală , funcția se execută normal și se revine
•unele func ții returnează un cod rezultat pentru apelant : un cod rezultat poate
indica succes sau e șec sau un tip de nereu șită
•cazul execu ției cu eroare este când apelantul face o gre șeală la valoarea
argumentele func ției sau o apelează pe aceasta într-un context nepotrivit
•execuția anormală apare în condiții care nu sunt sub controlul programului
(adresarea în afara spa țiului de memorie, erori de alocare a resurselor,
nereușită la căutarea fi șierelor => aceste situa ții este bine să fie tratate prin
excepții
•excepțiile sunt“aruncate”de codulîn cadrul c ǎruia apare o eroare și sunt
“prinse”de codul care poate corecta eroarea; odat ǎce o excep ție este
generatǎ, aceasta se propag ǎde la nivelul de imbricare la care a ap ǎrutînspre
blocurile exterioare, p înǎla gǎsirea unei instruc țiuni catch
•excepțiile care nu sunt “prinse”de-a lungul propag ǎrii, sunt tratate de un
handler general (global) de excep ții furnizat de sistem
Mecanismul try -catch-throw
•tratarea excep țiilorîn C# se bazează pe cuvintele -cheie:try,
catchșithrow.
•porțiunea de cod care se dore ște a fi monitorizată se include
într-un bloctry
•la apariția unei excep țiiîn blocultry, aceasta este generată
(cutrow)
•excepția este„prinsă”ulterior (cu catch)și procesată
•excepțiile sunt reprezentate prin clase derivate din Exception ,
care identific ǎtipul excep țieiși conțin detalii referitoare la
excepție
Generarea unei excep ții
•generarea unei excep ții implicǎcrearea unei instan țe a
unei clase derivate din Exception și“aruncarea ”
obiectului generat utiliz înd cuvîntul cheie throw.
private static void TestThrow()
{
//creare obiect exceptie
System.ApplicationException ex =
new System.ApplicationException
("Mesaj exceptie generate cu throw)");
throw ex;
}
“Prinderea ”unei excep ții
•În C#, o excep ție trebuie „prinsă”de uncatch imediat următor blocului care a
generat excep ția.Forma generală pentru tryșicatcheste:
try
{
// bloc try
}
catch(Exceptienoua1 e) {
// bloc catch 1
}
catch(Exceptienoua2 e) {
// bloc catch 2
}
//…
catch(ExceptinouaN e) {
// bloc catch N
}
catch(Exception e) {
// bloc pentru prinderea tuturor celorlalte exceptii
}
Mecanismul try -catch-throw
•dupǎgenerarea excep ției, mediul de execu ție verificǎdacǎaceasta este in interiorul unui
bloc try;
•dacǎda, orice bloc catch asociat lui try este verificat pentru a “prinde”excepția
•în mod normal, blocurile catch specific ǎtipuri de excep ții.
•corespunzător unui bloc try pot exista mai multe blocuri catch ; blocurile catch sunt
examinate în ordinea în care apar
•tipul excep ției primit ca argument este cel care determină care dintre ele v a fi folosit.
static void TestCatch()
{
try
{
TestThrow();
}
catch (System.ApplicationException ex)
{
System.Console.WriteLine(ex.ToString());
}
}
Tipuri de excep ții
•excepțiile pot fi de orice tip: tipuri predefinite sau clase
definite de utilizator.
•dacǎ nu se generează nici o excep ție, nu va fi executat nici
un bloc catch.
•dacă se generează o excep ție pentru care nu este definit un
bloc catch corespunzător , va apărea o eroare de terminare
anormală a programului .
•blocul catch nu este apelat, ci i se transferă execuția, adică
nu se mai revine în blocul try după generarea unei excep ții
•dacă eroarea care a generat excep ția poate fi remediată ,
execuția va continua cu ceea ce urmează după catch ;
uneori, eroa rea nu poate fi remediată și un bloc catch va
termina programul cu un apel la exit()sauabort()
Blocurile finally (1)
•pe lîngǎblocurile catch, o instruc țiune try poate con țineși un bloc
finally;
•practic, la apari ția unei excep ții,înainte de execu ția blocului catch
corespunz ǎtor, se verific ǎîntîi existența blocului finally.
•blocurile finally permit programatorului s ǎelimine orice stare
ambiguǎcare ar putea rezulta în urma execu ției cu eroare a
blocului try, sau s ǎelibereze resurse f ǎrǎa mai aștepta colectorul
de deșeuriîn acest scop.
•un bloc finally poate fi utilizat pentru a executa cod independe nt
dacǎo excepție a fost generat ǎsau nu; acest lucru poate fi necesar
în condițiileîn care codul care urmeaz ǎo construc ție de tipul
try/catch nu se mai execut ǎîn condițiile apariției unei excep ții.
•utilizarea unei instruc țiuni try fǎra cel puțin un bloc catch sau finally
genereaza o eroare de compilare
Blocurile finally (2)
try
{
// Cod de incercat la executie
}
catch (System.Exception ex)
{
// Cod pentru tratarea exceptiei
}
finally
{
// Cod de executet dupa try (si eventual, posibil catch)
}
Crearea unei excep ții
definite de utilizator
•utilizatorul va trebui s ǎ-și defineasc ǎpropria clas ǎde
excepții.
•clasa excep ție trebuie în mod obligatoriu s ǎfie derivat ǎdin
System.ApplicationException.
•în general, clasele de excep ție .NET au trei consstructori și
fiecare dintre ace știa apeleaz ǎde fapt constructorul clasei
de bazǎcorespunz ǎtor: un constructor f ǎrǎparametri, un
constructor cu un parametru (mesajul excep ției)și un
constructor cu doi parametri (mesajul excep țieiși
proprietatea Inner prin intermediul c ǎreia se poate
transmite excep ția respectiv ǎ) .
•clasa excep ție definitǎde utilizator trebuie s ǎdefineasc ǎ
toți cei trei constructori
Exemplu (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace NumePrenume
{
class ExceptieFormatNumeIncorect:
System.ApplicationException
{
public
ExceptieFormatNumeIncorect()
: base()
{
}public ExceptieFormatNumeIncorect
(string mesaj):base(mesaj)
{
}
public ExceptieFormatNumeIncorect
(string mesaj,
Exception exceptie)
: base(mesaj, exceptie)
{
}
}
}
Exemplu (2)
using System;
using System.Collections.Generic;
using System.Text;
namespace NumePrenume
{
class Persoana
{
string m_nume;
string m_prenume;
public string Nume
{
get { return m_nume; }
set { m_nume = value; }
}
public string Prenume
{
get { return m_prenume; }
set { m_prenume = value; }
}public override string ToString()
{
return m_nume+ " "+m_prenume;
}
public Persoana(string numeprenume)
{
try
{
string separator = "";
string[] tabel_separat
= numeprenume.Split
(separator.ToCharArray());
m_nume = tabel_separat[0];
m_prenume = tabel_separat[1];
}
catch (Exception ex)
{
throw new ExceptieFormatNumeIncorect
("Format incorect la
introducerea numelui si
prenumelui", ex);
}
}
}}
Exemplu (3)
•programul principal genereaz ǎun control de tipul ListBox în cadrul c ǎruia
introduce numele de persoane introduse în cîmpul de editare;
•dacǎformatul de introducere nu este corect, se generaz ǎo excepție.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace NumePrenume
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); }
Exemplu (4)
private void adauga_Click
(object sender, EventArgs e)
{
try
{
listaPersoane.Items.Add(new Persoana(nume_prenum e.Text));
}
catch (ExceptieFormatNumeIncorect exceptienume)
{
if (exceptienume.InnerException != null)
MessageBox.Show(exceptienume.Message + " \n" +
exceptienume.InnerException.Message);
else MessageBox.Show(exceptienume.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
nume_prenume.Text = "";
}
}
}
Delegați (delegate)
•în C++ există așa numitele func țiicallback: acestea utilizează
pointeri la func ții pentru a transmite func ții ca parametri altor
funcții.Delegațiiîn C# reprezintă o facilitate similară , dar mult mai
sigură din punctul de vedere al tipurilor dec ît poinerii din C++.
•pentru crearea unui delegat este nevoie de semnatura func țiilor
transmise acestuia: parametri, numele func ției, etc.
•delegații sunt de fapt clase ;în urma declara ției unui delegat,
acesta este derivat din clasele de bază care se referă la delega ți din
biblioteca .NET: System.MulticastDelegate sau System.Delegate
•dacă tipul returnat în cadrul delegatului este void, atunci în mod
automat acesta devine de tipul System.MulticastDelegate; acest t ip
suportă mai multe func ții prin utilizarea operatorului += . dacă tipul
returnatîn cadrul delegatului este diferit de void, atunci în mod
automat acesta devine de tipul System.Delegate și nu suportă
funcții multiple
Clasa Complex
class Complex
{
float real = 0;
float imag = 0;
public Complex
(float r, float i)
{
real = r;
imag = i;
}
public void SchimbaSemnR()
{
real = (real/2);
}public void SchimbaSemnI()
{
imag = (imag/2);
}
public void Afis()
{
Console.WriteLine
("numarul complex este: “
+real+" "+imag+"i ");
}
}
Crearea unui delegat
•au fost crea ți doi delega ți de tipul DelegatComplex și acestora li s –
au atașat cele două metode SchimbaSemnR șiSchimbaSemnI ale
clasei Complex
•fiecare delegat va “cunoaște”adresa func ției atașate
class Program
{
public delegate void DelegatComplex();
static void Main(string[] args)
{
Complex numar = new Complex(10, 20);
DelegatComplex d_real = new
DelegatComplex(numar.SchimbaSemnR);
DelegatComplex d_imag = new
DelegatComplex(numar.SchimbaSemnI);
Console.ReadKey();
}
}
Invocarea mai multor metode
•existăși posibilitatea de a crea un delegat de tipul de bază
System.MulticastDelegate căruia să -i atașam cei doi delega ți creați anterior;
întrucît funcțiile transmite returnează void , aceștia sunt automat de tipul
MulticastDelegate și deci, suportă invocarea mai multor metode :
MulticastDelegate m_del = d_real+d_imag;
•necesitatea utilizării referin țelor la func ții prin intermediul delega ților permite o
mai mare flexibilitate a codului rezultat; în abordarea clasică , algoritmii apelau
metodele direct prin nume; aceasta abordare limita într-o mare măsură
funcționalitatea codului generat în cazulîn care s-ar dori de exemplu apelul unor
metode diferite în funcție de contextul existent la un anumit moment dat
•problema poate fi generalizată și soluționatăîntr-o manieră mult mai elegantă
dacă se transmite unui algoritm un delegat și se lasă ca metoda con ținută,și pe
care delegatul o referă ,să poată fi diferită
•un exemplu în acest sens o reprezintă realizarea unei sortări a unui tablou de
persoane, o da tăîn funcție de nume și o datăîn funcție de vîrsta acestora; me toda
de sortare este generală ,și utilizează un delegat : funcția asociată delegatului
diferăînsă funcție de tipul sortării dorite
Exemplu (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace Delegati
{
public delegate int Comparator
(object obj1, object
obj2);
class Persoana
{
public string Nume = null;
public int Virsta = 0;
public Persoana
(string nume, int virsta)
{
Nume = nume;
Virsta = virsta;
}// metoda handler a delegatului
public static int ComparaNume
(object pers1, object pers2)
{
string n1 =
((Persoana)pers1).Nume;
string n2 =
((Persoana)pers2).Nume;
if (String.Compare(n1, n2) > 0)
{
return 1;
}
else if (String.Compare(n1, n2) < 0)
{
return -1;
}
else
{
return 0;
}
}
Exemplu (2)
//a doua metoda handler a delegatului
ComparaVirsta
public static int
ComparaVirsta
(object pers1, object
pers2)
{
int v1 =
((Persoana)pers1).Virsta;
int v2 =
((Persoana)pers2).Virsta;
if (v1 > v2)
{
return 1;
}
else if (v1 < v2)
{
return -1;
}
else
{
return 0;
}
}class UnDelegat
{
Persoana[] tablou = new Persoana[5];
public UnDelegat()
{
tablou[0] = new Persoana("Ioana", 11);
tablou[1] = new Persoana("Radu", 16);
tablou[2] = new Persoana("Camelia", 14);
tablou[3] = new Persoana("Diana", 17);
tablou[4] = new Persoana("Andrada", 19);
}
public void TiparireTablouSortat()
{
Console.WriteLine("Persoanele sunt: ");
foreach (Persoana p in tablou)
{
Console.WriteLine
("Nume = "+p.Nume+ " Virsta =
"+p.Virsta);
}
}
Exemplu (3)
public void Sortare
(Comparator compara)
{
object temp;
for (int i = 0;
i < tablou.Length; i++)
{
for (int j = i;
j < tablou.Length; j++)
{
// utilizarea delegatului compara ca și o
// metoda obi șnuită
if (compara(tablou[i],
tablou[j]) > 0)
{
temp = tablou[i];
tablou[i] = tablou[j];
tablou[j] = (Persoana)temp;
}
}
}
}static void Main(string[] args)
{
UnDelegat del = new UnDelegat();
//instantiem delegatul cu metoda handler
//Persoana.ComparaNume
Comparator cmpn =
new
Comparator(Persoana.ComparaNume);
//realizam sortarea elementelor functie de nume
del.Sortare(cmpn);
del.TiparireTablouSortat();
//instantiem delegatul cu metoda handler
Persoana.ComparaVirsta
Comparator cmpv = new
Comparator(Persoana.ComparaVirsta);
//realizam sortarea elementelor functie de virsta
del.Sortare(cmpv);
del.TiparireTablouSortat();
Console.ReadKey();
}
Exemplu (4)
Evenimente
•utilitatea delega ților stă nu numai în aceea că ace știa conțin referințe la
funcții, darșiîn aceea că se pot defini și utiliza numele func țiilor doar în
momentul execu țieiși nuîn momentul compilării
•unul din scopurile importante ale proiectării delega ților stăîn
aplicabilitatea acestora în modelul evenimentelor din .NET Framework
•evenimentele sunt ac țiuni ale sistemului sau rezultate în urma
manipulărilor utilizatorului (clickpe mouse, apăsarea unei taste , etc.) sau
pot fi declan șate de program
•atunci cînd se utilizează evenimente , trebuie declarat un delegat și apoi
un eveniment care utilizează tipul delegatului respectiv ; de asemenea,
trebuie creată o metodă handler care să trateze evenimentul resp ectiv
•în C# un eveniment este un membru a unei clase și este activat atunci c înd
evenimentul pentru care a fost definit se declan șează; de fiecare dată c înd
un eveniment este declan șat, se invocă o metodă definită anterior ,
specifică
Evenimente si delegati (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace Delegati
{
class Complex
{
//declarare delegat
public delegate void
ComplexHandler(string msg);
//declarare eveniment pt. obiecte Complex
// care utilizează tipul delegat
public static event
ComplexHandler Schimba;
float real = 0;
float imag = 0;
public Complex(float r, float i)
{
real = r;
imag = i;
}public void SchimbaSemnR()
{
real = (real/2);
Console.WriteLine("Declansare eveniment
//Shimba semn partea reala! //");
//declansare eveniment
Schimba
("Shimba semn partea reala");
}
public void SchimbaSemnI()
{
imag = (imag/2);
Console.WriteLine("Declansare eveniment
//Shimba semn partea imaginara! //");
//declansare eveniment
Schimba("Shimba semn partea
imaginara");
}
public void Afis()
{
Console.WriteLine
("numarul complex
este: "+real+" "+imag+"i ");
}
}
Evenimente si delegati (2)
class Program
{
// functie handler a evenimentului conforma cu semnatura delegat ului definit
private static void
OnSchimbaComplex(string msg)
{
Console.WriteLine("In functia OnSchimbaComplex! ");
Console.WriteLine("Tratam evenimentul : "+msg);
}
static void Main(string[] args)
{
Complex numar = new Complex(10, 20);
//adaugare handler pentru evenimentul declarat
Complex.Schimba += new
Complex.ComplexHandler(OnSchimbaComplex);
//declansare eveniment si apel functia h andler a evenimentului OnSchimbaComplex
numar.SchimbaSemnI();
Console.WriteLine
numar.SchimbaSemnR();
Console.ReadKey();
}
}
}
Evenimente si delegati (3 )
Evenimente și delegați predefini ți (1)
•evenimentele și delegații sunt utiliza ți impreună pentru a furniza diverse func ționalități unui
program
•în cele mai multe cazuri, programarea Windows bazată pe evenimente utilizează evenimente
și delegați predefini ți
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Evenimente
{
class UnEveniment: Form
{
public UnEveniment()
{
Button click = new Button();
click.Parent = this;
click.Text = "Apasa!";
click.Location = new Point(100, 100);
//adauga handler pentru evenimentul Click
click.Click += new EventHandler(OnClick);
}
Evenimente și delegați predefini ți (2)
public void OnClick
(object sender, EventArgs ea)
{
MessageBox.Show("Tocmai ati dat
click pe buton!");
}
}
static class Program
{
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault
(false);
Application.Run(new UnEveniment());
}
}
}•evenimentul Click există și
este definit pentru clasa
Button
•delegatul EventHandler
există deja în spa țiul de nume
System din biblioteca de clase
.NET Frameworks.
• trebuie să se definească
metoda (numi tă șicallback
method ) care să fie invocată
atunci c înd este declan șat
evenimentul Click (apăsare pe
buton); la defini ția acesteia
trebuie să se țină cont de
semnătura impusă de delagatul
pre-existent al evenimentului
EventHandler , metoda fiind
obligatoriu să fie conformă
acestei semnături
Definirea evenimentelor și delegatilor
de către utilizator
•altă clasă poate apoi să -și definească (înregistreze) metode pri n care să trateze
evenimentul respectiv
•tratarea evenimentului are loc prin intermediul unui delegat, ca re specifică
semnătura metodei care este inregistată pentru tratarea evenimen tului respectiv;
delegatul poate fi unui din delega ții predefini țiîn .NET Framework sau unul
declarat de utilizator
•delegatul se asignează evenimentului ,și astfel se înregistrează efectiv metoda care
va fi apelată atunci c înd evenimentul se declan șează
•declararea evenimentelor se face cu ajutorul cuv întului cheie event, asociindu -i-se
de asemenea și un delegat, pe care evenimentul respectiv este declarat că îl
acceptă:
public event Delegat Eveniment;
•sintaxa += înregistrează practic un delegat pentru un eveniment :
Eveniment+=new Delegat(OnEveniment);
•pentru așterge oînregistrare a unui delegat pentru un anumit eveniment se
poate utilize sintaxa -=într-o manieră similară
•declanșarea unui eveniment se realizează asemănător cu un apel de metod ă:
Eveniment();
•utilizarea evenimentelor și delegaților predefini ți este foarte simplă ; din acest
motiv este de preferat să se verifice ce există deja definit înainte de a crea
propriile evenimente și delegați
Exemplu
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Evenimente
{
//declararea delegatului pentru eveniment
public delegate void Delegat();
class UnEveniment: Form
{
//declararea evenimentului
// cu delegatul asignat
public event Delegat
Eveniment;
public UnEveniment()
{
//cream un eveniment propriu si ii
// inregistram un delegat
Eveniment+=new
Delegat(OnEveniment);
//declansam evenimentul
MessageBox.Show
("S-a declansat evenimentul!");
Eveniment();
}//metoda care trateaza evenimentul
public void OnEveniment()
{
MessageBox.Show("Se trateaza
evenimentul!");
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRendering
Default(false);
Application.Run
(new UnEveniment());
}
}
}
Iesirea exemplului
Atribute
•atributele sunt elemente (clase care pot fi scrise în C# )care permit
adăugarea unor informa țiiîn format declarativ în cadrul programelor
•aceste informa ții sunt utilizate ulterior at ît la execu ție cîtșiîn procesul de
proiectare a aplica ției (de exemplu de către uneltele de dezvoltare
utilizate)
•atributele reprezintă un mecanism prin intermediul căruia se pot adăuga
metadate în programe (instruc țiuni de compilare, date despre datele,
claseleși metodele utilizate în cadrul programului, etc.)
•sunt necesare deoarece multe din serviciile care sunt ob ținute de pe urma
utilizării atributelor ar fi foarte dificil de ob ținut prin scrierea de cod sursa
echivalent
•atunci cînd un program C# este compilat, acesta este convertit într-un
limbaj intermediar MSIL (MicroSoft Intermmediate Language) și se crează
un fișier numit ansamblu care,în mod normal poate fi un executabil sau o
bibliotecă .dll
•ansamblele sunt auto -descriptive deorece con țin toată informa ția
(metadatele) necesară
Exemplu definire atribute (1)
•clasa prin intermediul căreia se define ște atributul
ObsoleteAttribute este definită în felul următor
(Spațiul de nume System, în mscorlib.dll):
[SerializableAttribute]
[ComVisibleAttribute(true)]
[AttributeUsageAttribute(AttributeTargets.Class|AttributeT
argets.Struct|AttributeTargets.Enum|
AttributeTargets.Constructor|AttributeTargets.
Method|AttributeTargets.Property|
AttributeTargets.Field|AttributeTargets.Event|
AttributeTargets.Interface|AttributeTargets.
Delegate, Inherited=false)]
public sealed class ObsoleteAttribute : Attribute
Exemplu definire atribute (2)
•se observă utilizarea modificatorului sealed prin intermediul că reia se
marchează faptul că din respectiva clasă nu pot fi derivate alte clase
•un atribut este un obiect care reprezintă date care se doresc as ociate cu
un element din cadrul programului
•elementul căruia i se asociază un atribut reprezintă ținta atributului
respectiv
•atributele se aplică de regulă înaintea declara țiilor de tipuri sau membri ai
unor tipuri, acestea reprezent înd implicit ținta acestora
•se utilizează paranteze drepte pentru definirea atributelor
[ObsoleteAttribute]
•partea de “attribute”din cadrul numelui e op țională, deci o variantă
echivalentă ar fi :
[Obsolete]
Exemplu utilizare atribute (1)
using System;
using System.Collections.Generic;
using System.Text;
namespace Atribute
{
public class DemoAtribute
{
[Obsolete]
public void PrimaMetodaDeprecated()
{
Console.WriteLine
("Apel PrimaMetodaDeprecated() :");
}
[ObsoleteAttribute]
public void AdouaMetodaDeprecated()
{
Console.WriteLine
("Apel AdouaMetodaDeprecated() :");
}
Exemplu utilizare atribute (2)
[Obsolete("Aceasta metoda nu mai trebuie utilizata", true)]
public void AtreiaMetodaDeprecated()
{
Console.WriteLine
("Apel AtreiaMetodaDeprecated() :");
}
}
class Program
{ [STAThread]
static void Main(string[] args)
{
DemoAtribute atribut = new DemoAtribute();
atribut.PrimaMetodaDeprecated();
atribut.AdouaMetodaDeprecated();
atribut.AtreiaMetodaDeprecated();
Console.ReadKey();
}
}
}
Rezultatul utilizării atributelor (1)
•este obținutîn urma compilării programului ,și constă din 3 warning-uri
corespunzătoare celor 3 utilizări ale metodelor respective
•cel de-al treilea atribut av îndși un parametru, afi șează după mesajul
standard și textul con ținutîn parametrul respectiv
Rezultatul utilizării atributelor (2)
Categorii de atribute (1)
•atributele pot fi de două categorii : intrinseci, sau predefinite respectiv
definite de utilizator, prin i ntermediul acestora din urmă fiind posibilă
extinderea limbajului cu sintaxe de atribute customizate
•atributele predefinite sunt furnizate ca parte a Common Language
Runtime(CLR)și sunt integrate în platforma . NET. Această categorie de
atribute este cea mai utilizată , chiar dacă atributele definite de utilizator
pot constitui o unealtă foarte puternică atunci c înd sunt combinate cu
mecanismul de reflexie –reflection
•există posibilitatea de a adăuga parametri unor atribute , fiind posibilă
utilizarea a două tipuri de parametri : parametri pozi ționaliși parametri cu
nume
•parametri cu nume sunt întotdeauna op ționali; parametri pozi ționali pot
fi eventual omi și
•atributul [Obsolete] are un parametru pozi țional de tip bool care, da că e
true, forțează o eroare la compilare în loc de un simplu warning.
Categorii de atribute (2)
[Obsolete("Aceasta metoda nu mai
trebuie utilizata", true)]
public void AtreiaMetodaDeprecated()
Categorii de atribute (3)
Domeniul de aplicabilitate al
atributelor
•domeniul de aplicabilitate al atributelor nu se rezumă însă doar la metode
•ținta(target-ul) atributelor poate fi: all (aplicabil la tot), assembly
(aplicabil în cadrul ansamblului), class (aplicabil clasei), method (aplicab il
metodei)
•specificarea explicită a țintei unui atribut poate fi realizată ori de c îte ori
pot exista ambiguită ți, prefixînd atributul cu numele țintei:
[assembly:CLSCompliant(true)]
•atributul [CLSCompliant] este utilizat pentru a asigura faptul c ăîntregul
ansamblu este în conformitate cu specifica țiile theCommon Language
Specificatio n (CLS)
•CLS reprezintă un set de standarde care permite comunicarea între
diferitele limbaje furnizate pentru platforma .NET
•declarația de mai sus indică faptul că atributul se va aplica întregului
ansamblu
Atribute predefinite
•spațiul de nume System.Ru ntime oferă o serie de atribute predefinite
inclusiv atribute pentru ansamble, configurare și versionare
•prin intermediul atributului AssemblyVersion se poate asocia inf ormatia
despre versiunea programului respectiv:
[assembly: AssemblyVersion( “1.0.2 ”)]
•din aceea și categorie mai fac parte si atributele:
AssemblyCompanyAttribute,
AssemblyConfigurationAttribute,
AssemblyCopyrightAttribute, AssemblyCultureAttribute,
AssemblyDescriptionAttribute,
AssemblyProductAttribute, AssemblyTitleAttribute,
AssemblyTrademarkAttribute.
•atribute specifice sunt utilizate în procesul de serializare, de exemplu
atributul:
System.Reflection.TypeAttributes.Serializable
•este utilizat pentru a indica faptul că obiectele din respectiva clasă sunt
serializabile.
[System.Serializable]
Reflexia-Reflection
•mecanismul reflexiei reprezintă procesul prin care un program poate să -și
citească propriile metadate
•se spune că programul se reflectă asupra lui însuși,extrăgînd metadatele
din ansamblul său și utilizînd informa țiile fie pentru a informa utilizatorul
sau pentru a -și modifica propriul comportament
•reflexia furnizează obiecte (în general, de tipul Type) care încapsulează
ansambluri, module și tipuri. Mecanismul de reflexie este util în
următoarele situa ții:
–atunci cînd este necesar accesul atributelor din cadrul metadatelor
programelor
–pentru examinarea și instanțierea tipurilor în cadrul ansamblelor
–pentru crearea de noi tipuri la executie (utiliz înd System.Reflection.Emit)
–pentru a realiza legarea dinamica (late binding) și accesarea metodelor
tipurilor create în momentul execu ției
Utilizarea reflexiei (1)
•clasele din spa țiul de nume System.Reflection împreună cu System.Type permit
obținerea de informa ții despre ansamblele încărcate, despre tipurile definite în
cadrul acestora, etc.
•un exemplu simplu de utilizare a mecanismului de reflection îl reprezintă utilizarea
metodei statice GetType(), car e este definită în clasa Object și moștenităîn cadrul
tuturor tipurilor:
int i = 30;
System.Type type = i.GetType();
System.Console.WriteLine(type);
•ieșirea secven ței de mai sus indică tipul intreg ,și anume:
System.Object Item [Int32]
System.Int32
Utilizarea reflexiei (2)
•clasa Type este una dintre cele mai importante în contextul mecanismului de
reflexie
•Common Language Runtime (CLR) creează un obiect Typepentru un anuit tip,
atunci cînd acest lucru este solicitat; ulterior, pot fi utilizate propri etățileși
metodele obiectului Typepentru a ob ține informa ții asupra tipului respectiv:
using System;
using System.Collections;
using System.Reflection;
class Info
{// determina tipul si informatii despre membri acestuia
public static void Main(string[] args)
{
Type tip = typeof(System.Collections.ArrayList);
Console.WriteLine (" \nReflection.MemberInfo");
Utilizarea reflexiei (3)
// determina tipul si informatii despre membri acestuia -o alta varianta
Type tip =Type.GetType ("System.Collections.ArrayList");
//clasa System.Reflection.MemberInfo obtine informatii despre a tributele unui membru
MemberInfo[] TipTabelMembri = tip.GetMembers();
Console.WriteLine(" \n Sunt {0} membri in {1}.",
TipTabelMembri.Length, tip.FullName);
//afiseaza toti membri clasei ArrayList (65)
for (int i = 0; i < TipTabelMembri.Length; i++)
{
Console.WriteLine(TipTabelMembri[i]);
}
Console.ReadKey();
}
}
Fire de executie (thread -uri)
•limbajul C# supor tă execuție paralelă prin intermediul multithreading -ului
•în acest sens, un fir de execu ție (thread) reprezintă o cale independentă
de execuție care se desfă șoarăîn paralel cu alte căi de execu ție
•intern,multithreading -ul este controlat de un planificator, o func ție pe
care CLR-ul o delegă către sistemul de operare ; la o execu ție pe un singur
procesor planificatorul utilizează un algoritm de planificare ba zat pe
cuantă de timp fixă (time-slicing)
•în majoritatea cazurilor un threadnu are nici un control asupra
momentului în care va fi întrerupt datorită time-slicing-ului;în general,
sub Windows XP cuanta de timp este de ordinul a zeci de milisecu nde,
semnificativ mai mare dec ît timpul necesar pentru schimbarea contextului
(care este, în mod tipic de ordinul a c îteva microsecunde)
•în cazul unui sistem multiprocessor, multithreading -ul este implementat
printr-un amestec de time-slicingși procesare paralelă
Utilitatea firelor de execu ție
•utilizarea firelor de execu ție este benefică atunci c înd dorim să executăm
anumite procese (metode, calcule, etc.) consumatoare de timp în
background
•în mod deosebit aplica țiile de tipul Windows Forms beneficiază de
avantajele utilizării firelor de execu ție,în special pentru procesarea
interacțiunii cu utilizatorul prin intermediul mouse -ului sau tastaturii;
altfel, dacă thread -ul principal este implicat în diverse alte procesări
complexe, în acest timp intrările provenite de la mouse sau tastatură nu
ar putea fi preluate și aplicația ar deveni non -responsivă
•în general, o aplica ție C#poate fi constituită din mai multe fire de
execuție fie explicit (prin crearea și lansarea în execuție a mai multor
thread-uri) sau utiliz înd facilitatea .NET de a crea thread-uriîn mod
implicit
•multithreading -ul areînsăși dezavantaje, rezult înd de cele mai multe ori
în programe mai complexe și necesitînd resurse de sistem suplimentare
(pentru alocarea firelor de execu țieși schimbările de context )
Crearea firelor de execu ție
•se crează utiliz înd clasa Thread din spa țiul de nume System.Threading, și
transmițîndu-iîntr-un delegat ThreadStart metoda pe care se dore ște să o
lansezeîn execuție thread-ul respectiv, sub forma:
public delegate void ThreadStart();
Threadnume_thread = new Thread
(new ThreadStart( nume_metoda ));
Exemplu –creare thread (1)
using System;
using System.Threading;
using System.Text;
namespace Firexec
{
class Program
{
static void Main(string[] args)
{
//creare thread
Thread th = new Thread(
new ThreadStart(Afisare));
Exemplu –creare thread (2)
// o alta varianta prescurtata
Thread th = new Thread(Afisare);
// pornire thread
th.Start();
for (int i=0; i<100; i++) Console.Write("Main");
Console.ReadKey();
}
static void Afisare()
{
for (int i = 0; i < 100; i++)
Console.Write(i +"Afisare");
}
}
}
Thread-uri cu parametri
•există posibilitatea de a transmite date (parametri) thread-urilor
•în acest caz nu mai este posibilă utilizarea delegatului ThreadSt art
deoarece acesta un acceptă parametri
•se poate utiliza în acest stop un alt delegat, ParameterizedThreadStart,
care acceptă un singur argument de tip object :
public delegate void
ParameterizedThreadStart(object obj);
Threadnume_thread = new Thread(new
ParameterizedThreadStart( nume_metoda(param) ));
Exemplu –thread cu parametri (1)
using System;
using System.Threading;
using System.Text;
namespace Firexec
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.Name = "MAIN";
Thread th = new Thread
(new ParameterizedThreadStart(Afisare));
th.Name = "TH";
th.Start(true);
Afisare(false);
Console.ReadKey();
}
Exemplu –thread cu parametri (2)
static void Afisare(object par_maj)
{
bool maj = (bool)par_maj;
Console.WriteLine(par_maj ? "AFISARE CU
MAJUSCULE din " +
Thread.CurrentThread.Name :
"afisare fara majuscule din " +
Thread.CurrentThread.Name);
}
}
}
•funcție de valoarea parametrului transmis, se va afi șa textul cu majuscule
sau nu.
Proprietă țile firelor de execu ție
•firelor de execu ție li se poate asigna un nume (MAIN respectiv TH) și că
numele acestora poate fi referit prin intermediul proprietă ții
CurrentThread.Name.
•clasa Thread con ține de asemenea și alte proprietă ți prin intermediul
cărora se pot seta /obține informa ții legate de thread-ul curent, ca de
exemplu: nume (Name), prioritatea (Priority), starea thread -ului
(ThreadState), etc.
•proprietatea IsBackground controlează maniera de execu ție athread-ului:
în background (true) sau nu (false); trebuie men ționatînsă faptul că
schimbarea proprietă ții nu afectează prioritatea și/sau starea procesului
respectiv.
Crearea firelor de execu ție
utilizînd metode anonime (1)
•reprezintă o altă alternativă de creare a unui fir de execu ție
•avantajul metodelor anonime constă în aceea că acestea pot avea mai
mulți parametri (fa ță de ThreadStart și ParameterizedThreadStart care nu
acceptă dec ît metode cu nici un parametru respectiv cu un singur
parametru):
using System;
using System.Threading;
using System.Text;
namespace Firexec
{
class Program
{
static void Main(string[] args)
{
Crearea firelor de execu ție
utilizînd metode anonime (2)
//utilizare metoda anonima
Thread th = new Thread(delegate()
{Afisare(50," Parametru text de afisat "); });
th.Start();
for (int i=0; i<50; i++) Console.Write("Main");
Console.ReadKey();
}
static void Afisare(int cit, string text)
{
for (int i = 0; i < cit; i++)
Console.Write(text);
}
}
}
Coordonarea și sincronizarea firelor
de execuție (1)
•pentru coordonarea ac țiunilor firelor de execu ție pot fi utilizate diferite
metode de blocare a execu ției acestora, printre care:
•Sleep, care “adoarme” respectiv blochează thread -ul pentru o perioadă
definită de timp , specificată ca parametru
•Join, care a șteaptă pînă cînd un alt thread își termină execu ția
namespace Firexec
{
class Program
{
static void Main(string[] args)
{
Thread th = new Thread
(new ThreadStart(Afisare));
th.Start();
Coordonarea și sincronizarea firelor
de execuție (2)
//asteapta pina la terminarea thread -ului th
th.Join();
Console.Write("S -a terminat th, suntem in Main");
Console.ReadKey();
}
static void Afisare()
{
for (int i = 0; i < 100; i++)
Console.Write("In thread -ul th!");
}
}
}
Utilizarea de date în comun
•firele de execu ție pot să utilizeze date în comun; o metodă de a realiza
acest lucru implică utilizarea c împurilor de date statice
•accesul la datele utilizate în comun trebuie însă realizat în excludere
mutuală, pentru a asigura consisten ța datelor comune
•C#furnizează diverse modalită ți: lock, Mutex, Semaphore; ele sunt
similare, cu mici deosebiri:
•Mutex, spre deosebire de lock func ținonează pentru procese multiple
•Semaphore reprezintă un lock generalizat , care permite accesul a unui
număr de thread-uri dat de capacitatea sa (parametru); de asemenea, un
Semaphore nu are proprietar, orice thread poate să elibereze resursa , nu
doarthread-ul care a ob ținut-o, caîn cazul Mutex -ului sau lock -ului
Exemplu (1)
using System;
using System.Threading;
using System.Text;
namespace Firexec
{
class Program
{
static int comun=0;
static object blocat =
new Object();
static void Main(string[] args)
{
Thread th = new Thread(Afisare);
th.Start(); //intirzie thread -ul 5 ms
Thread.Sleep(5);
for (int i = 0; i < 100; i++)
{
// modificare
comun += 1;Console.WriteLine("S -a modificat
valoarea lui comun in Main " + comun);
}
Console.ReadKey();
}
static void Afisare()
{
//accesîn excludere mutuală
lock (blocat)
{
for (int i = 0; i < 100; i++)
{
//modificare
comun += 5;
Console.WriteLine("S -a modificat
valoarea lui comun in metoda
Afisare la " + comun);
}
}
}
} }
Exemplu (2)
class Program
{
static int[] tablou = new
int[1000];
static int i=0;
static object blocat = new object();
static void Main(string[] args)
{
Thread th1 = new Thread
(new ThreadStart(Adaugare));
Thread th2 = new Thread
(new ThreadStart(Adaugare));
th1.Name = "TH_1";
th2.Name = "TH_2";
th1.Start();
th2.Start();
Console.ReadKey();
}static void Adaugare()
{
Random rand = new Random();
bool gata = false;
while (!gata)
{lock (blocat)
{ if (i < 1000)
{
Console.Write(Thread.CurrentThread.
Name + " : ");
Console.Write("Adauga elementul "
+ i.ToString() + " = ");
tablou[i] = rand.Next(1000);
Console.WriteLine
((tablou[i]).ToString());
i++;
} else
{
Console.WriteLine("Gata!");
gata = true;
}
}
Rezultatul executiei
Execuția programului
•maniera de execu ție se poate schimba func ție de granularitatea
porțiunii de cod asupra căruia se aplica lock-ul: acesta este aplicat numai
asupra codului corespunzător unei itera ții din cadrul func ției Adaugare,
accesulîn excludere mutuală utiliz înd lock nu prezintă un overhead
suplimentar semnificativ, lock-ulînsuși fiind foarte rapid.
Totuși, pot exista și dezavantaje:
•scade nivelul concuren ței dacă prea mult cod este prins în cadrul unui
lock, cauz înd blocarea inutilă a celorlalte thread -uri
•apariția deadlock -ului este posibilă dacă lock -urile sunt utilizate defectuos
•de asemenea, trebuie avut în vedere faptul că , controlul accesului în
excludere mutuală către un obiect utiliz îndlockva func ționa numai dacă
toate firele de execu ție concurente sunt con știente de acest lucru și
folosesclock-ul respectiv; cu c ît domeniul de valabilitate al obiectelor
respective este mai vast, cu at ît este mai greu de realizat acest lucru
ADO.NET -Caracteristici generale
•reprezintă un set de biblioteci orientate pe obiecte care permit
interacțiunea aplica țiilor cu diverse surse de date: baze de date de
diferite tipuri (Microsoft SQL Server, Microsoft Access, Oracle,
Borland Interbase, IBM DB2, etc.) dar și date con ținuteîn fișiere de
tip XML, Excel sau text
•datorită diversită ții de tipuri de surse de date sunt necesare
protocoale diferite (specifice) de comunicare cu acestea: anumit e
surse de date utilizează protocolul ODBC , altele protocolul OleDb,
altele comunică cu sursa de date direct prin itermediul claselor
ADO.NET.
•modalitatea de comunicare cu sursele de date este aceea și,însă se
bazează pe seturi de biblioteci specifice , fiecare dintre acestea
identificînd prin intermediul prefixului furnizorul de sursă de date
(provider-ul) respectiv
Tipuri de furnizori de surse de date și
prefixele corespunzătoare
Nume furnizor
(provider)Prefix API Descriere
ODBC Data Provider Odbc Surse de date cu interfa ță
ODBC
OleDb Data Provider OleDb Surse de date cu interfa ță
OleDb
Oracle Data Provider Oracle Baze de date Oracle
SQL Data Provider Sql Pentru interac țiunea cu
Microsoft SQL Server.
Borland Data Provider Bdp Acces generic la baze de date
tip Interbase, SQL Server,
IBM DB2 și Oracle
Obiecte specifice – bază de date
Microsoft SQL (1)
•sunt cuprinse în spațiul de nume System.Data.SqlClient
•obiectulSqlConnection – este utilizat pentru crearea unei conexiuni
către baza de date și setarea caracteristicilor specifice conexiunii:
serverul de baze de date utilizat, numele bazei de date, numele
utilizatorului, parola, eventual al ți parametri suplimentari necesari
pentru realizarea conexiunii; obiectul SqlConnection creat este apoi
utilizatîn continuare de în general de obiecte de tip SqlCommand
pentru a identifica baza de date către care este destinată coman da
respectivă
•obiectulSqlCommand – este utilizat pentru a trimite comenzi SQL
către baza de date ; obiectul SqlCommand utilizează un obiect
SqlConnection pentru a identifica baza de date asupra căreia să
aplice comanda respectivă . Există mai multe modalită ți de da
trimite o comandă utiliz înd un obiect SqlCommand: fie direct, prin
intermediul acestuia, fie transmi țînd o referin ță către obiectul
SqlCommand unui obiect de tipul SqlDataAdapter.
Obiecte specifice – bază de date
Microsoft SQL (2)
•ObiectulSqlDataReader permite ob ținerea rezultatelor unei
comenzi SQL de tipul SELECT de la un obiect SqlCommand; datele
returnate de la un obiect de tip SqlDataReader sunt sub forma un ui
stream de date rapid de tipul forward -only, ceea ce conduce la o
manipulare foarte rapidă a datelor dar numai într-o manieră
secvențială
•ObiectulDataSet– constă dintr -o reprezentare în memorie a
datelor, sub fo rmă tabelară bazată pe r înduriși coloane. Este
destinat manipulării datelor în memorie în scopul de a limita
conexiunile către baza de date și de a putea accesa informa țiile din
bazăîn modul deconectat, atunci c înd acest lucru este posibil.
Obiectul DataSet este generic pentru to ți furnizorii de date, și din
acest motiv nu are prefix specific
•ObiectulSqlDataAdapter –permite managementul datelor într-o
manieră deconectată de la baza de date , prin intermediul unui
obiect DataSet.
Pasi pentru accesul unei baze de date
•se crează o conexiune prin instan țierea unui obiect
SqlConnection
•se deschide conexiunea, apel înd metoda Open a
obiectului SqlConnection
•se transmite obiectul conexiune creat către alte obiecte
ADO.NET , prin intermediul cărora se realizează diferite
operații asupra bazei de date
•seînchide conexiunea apel înd metoda Close a obiectului
SqlConnection
Conexiunea către o bază de date
•conexiunile reprezintă resurse extrem de importante și,în
aplicațiile de dimensiuni mari cu număr mare de utilizatori ai
aceeași baze de date, numărul acestora la un anumit moment dat
trebuie limitat din considerente de performan ță
•fiecare conexiune induce o încărcare suplimentară cu efecte
negative asupra performan țeiși scalabilită ții aplicației
•la crearea unui obiect conexiune, pot fi specifica ți următorii
parametri ( în cadrul unui șir de caractere):
–Data Source – identifică serverul
–Initial Catalog –numele bazei de date
–Integrated Security – se setează SSPI pentru a realiza conexiunea
utilizînd login-ul Windows al utilizatorului
–User ID–numele utilizatorului configurat în serverul SQL
–Password – parola corespunzătoare User ID de pe serverul SQL
Utilizarea obiectelor SqlConnection,
SqlCommand și SqlDataReader (1) –
exemplu de utilizare a unei baze de date MicroSoft SQL numită DB TEST aflată pe serverul TOSHIBA _DOINA,și
care conține un tabel Firme cu date despre firme (Nume, Tara, Adresa, NrA ngajati)
using System;
using System.Data;
using System.Data.SqlClient;
namespace DBTestApp
{
class AccesDate
{
SqlConnection conn;
//constructor -seteaza parametri conexiunii
public AccesDate()
{
conn = new SqlConnection
("Data Source=TOSHIBA_DOINA;
Initial Catalog=DBTEST;
Integrated Security=SSPI");
}static void Main(string[] args)
{
AccesDate acc =
new AccesDate();
acc.CitireDate();
Console.ReadKey();
}
Utilizarea obiectelor SqlConnection,
SqlCommand și SqlDataReader (2)
public void CitireDate()
{
SqlDataReader rdr = null;
try
{
// deschide conexiunea
conn.Open();
// instantiaza o noua comanda cu o interogare
SqlCommand cmd =
new SqlCommand
("select * from Firme", conn);
//obține rezultatele interogarii in obiectul rdr
rdr = cmd.ExecuteReader();
// afiseaza coloanele 0,1,2 si 4
//a fiecarei inregistrari
while (rdr.Read())
{
Console.WriteLine("Nume:
"+rdr[0]);
Console.WriteLine("Tara:
"+rdr[1]);Console.WriteLine("Adresa:
"+rdr[2]);
Console.WriteLine("NrAngajati:
"+rdr[4]);
Console.WriteLine();
}
}
finally
{
if (rdr != null)
{
rdr.Close();
}
// inchide conexiunea
if (conn != null)
{
conn.Close();
}
}
}
Utilizarea obiectelor SqlConnection,
SqlCommand și SqlDataReader (3)
•se observă în exemplul de mai sus utilizarea blocurilor de
tiptry/finally pentru a se asigura faptul că nu se încearcă
nici o opera ție pînă cînd nu se reu șeste deschiderea
conexiunii ( în caz contrar se generază o excep ție);
•pentru a evita situa țiaîn care răm înd conexiuni neutilizate
deschise, secven ța deînchidere a conexiunii a fost inclusă
într-un bloc finally (c are garantează faptul că respectiva
porțiune de cod va fi întotdeauna executată , indiferent
dacă apare sau nu o excep ție).
•metodele Openrespectiv Closeale obiectului
SqlConnection sunt utilizate pentru deschiderea respectiv
închiderea conexiunii către baza de date .
Utilizarea obiectelor SqlConnection,
SqlCommand și SqlDataReader (4)
public void AltaCitireDate()
{SqlDataReader rdr = null;
// instantiaza o noua comanda cu o interogare
SqlCommand cmd = new
SqlCommand("select * from Firme",
conn);
try
{
// deschide conexiunea
conn.Open();
//creaza o instanta a obiectului SqlDataReader
rdr = cmd.ExecuteReader();
// afiseaza un tabel cu rezultatele -cap tabel
Console.WriteLine("Nume
Tara Adresa NrAngajati");
Console.WriteLine(" –-");
//citeste informatia din tabel
while (rdr.Read())
{
// preia rezultatele
string nume = (string)rdr["Nume"];string tara = (string)rdr["Tara"];
string adr =
(string)rdr["Adresa"];
int nr = (int)rdr["NrAngajati"];
// afiseaza rezultatele
Console.Write("{0, -30}", nume);
Console.Write("{0, -5}", tara);
Console.Write("{0, -15}", adr);
Console.Write("{0, -10}", nr);
Console.WriteLine();
}
}
finally
{
if (rdr != null)
{
rdr.Close();
}
// inchide conexiunea
if (conn != null)
{
conn.Close();
}
}
}
Utilizarea de interogări parametrizate
•pot fi transmi șiși parametri comenzilor care se vor
executa, parametri de obicei furniza ți de utilizator
prin intermediul interfe ței, pentru a particulariza o
anumită comandă .
•utilizarea de interogări parametrizate implică
realizarea următorilor pa și:
–construirea șirului de comandă utiliz înd parametri
–crearea unui obiect SqlParameter și asignarea acestuia cu
valoarea dorită
–adauga parametri obiectului comanda creat prin asignarea
proprietă țiiParameters a obiectului SqlCommand
Implementarea unei interogări
parametrizate
public void OALtaCitireDate
(string p_tara)
{
SqlDataReader rdr = null;
try
{
// deschide conexiunea
conn.Open();
// instantiaza o noua comanda prin construirea
//șirului de comandă utiliz înd parametri
SqlCommand cmd =
new SqlCommand("select * from
Firme where Tara=@otara",
conn);
//crearea unui obiect SqlParameter
SqlParameter param = new
SqlParameter();
//defineste parametri comenzii
param.ParameterName = "@otara";
param.Value = p_tara;
// adauga parametri obiectului comanda creat
cmd.Parameters.Add(param);//creaza o instanta a obiectului SqlDataReader
rdr = cmd.ExecuteReader();
// afiseaza coloanele 0,1,2 si 4 a fiecarei inregistrari
while (rdr.Read())
{
Console.WriteLine("Nume: " + rdr[0]);
Console.WriteLine("Tara: " + rdr[1]);
Console.WriteLine("Adresa: " + rdr[2]);
Console.WriteLine("NrAngajati: " + rdr[4]);
Console.WriteLine();
}
}
finally
{
if (rdr != null) // inchide conexiunea
{ rdr.Close(); }
if (conn != null)
{conn.Close(); }
}
}
Alte comenzi trimise prin intermediul
obiectului SqlCommand
•prin intermediul obiectului SqlCommand pot fi
transmise și alte comenzi în afară de SELECT , cum
ar fi comenzi de actualizare a bazei de date prin
inserția,ștergerea sau modificarea unor
elemente.
•exemplul anterior poate fi completat cu
metodele InsertDate ,ActualizeazaDate și
StergeDate care realizează aceste opera ții +
metodaNumarInregistrar i care returmeaza
numarul de inregistrari din baza de date
MetodaInsertDate
public void InsertDate()
{
try
{
conn.Open(); // deschide conexiunea
// creaza un sir cu comanda dorita -insertie date
string insertString = @"insert into Firme (Nume, Tara, Adresa,
NrAngajati) values
('SC ONouaFirma srl','RO ‘,'Barcaului 17','10')";
// instantiaza un obiect SqlCommand cu o n oua comanda non -query
SqlCommand cmd = new SqlCommand(insertString, conn);
//apel ExecuteNonQuery pentru a transmite comanda
cmd.ExecuteNonQuery();
}
finally
{ //inchide conexiunea
if (conn != null)
{
conn.Close();
}
}
}
Metoda ActualizeazaDate
public void ActualizeazaDate()
{ try
{
conn.Open(); // deschide conexiunea
// creaza un sir cu comanda dorita -actualizare date
string updateString = @"update Firme set Nume = 'SC So ft&Hard srl'
where Nume = 'SC ONouaFirma srl'";
// instantiaza un obiect SqlCommand cu o noua comanda non -query, fara a specifica conexiunea
SqlCommand cmd = new SqlCommand(updateString);
// seteaza proprietatea conexiune
cmd.Connection = conn;
//apel ExecuteNonQuery pentru a transmite comanda
cmd.ExecuteNonQuery();
}
finally
{ // inchide conexiunea
if (conn != null)
{ conn.Close(); }
}
}
Metoda StergeDate
public void StergeDate()
{ try
{
conn.Open();// deschide conexiunea
// creaza un sir cu comanda dorita -stergere date
string deleteString = @"delete from Firme
where Nume = 'SC ONouaFirma srl'";
//instantiaza un nou obiect SqlCommand fara parametri
SqlCommand cmd = new SqlCommand();
//seteaza proprietatea CommandText a obiectului SqlCommand
cmd.CommandText = deleteString;
//seteaza proprietatea Connection a obiectului S qlCommand
cmd.Connection = conn;
//apel ExecuteNonQuery pentru a transmite comand a
cmd.ExecuteNonQuery();
}
finally // inchide conexiunea
{
if (conn != null) { conn.Close(); }
}
}
Metoda NumarInregistrari
public int NumarInregistrari()
{
int count = -1;
try
{
conn.Open();
SqlCommand cmd =
new SqlCommand("select count(*)
from Firme", conn);
count = (int)cmd.ExecuteScalar();
}
finally
{
if (conn != null)
{
conn.Close();
}
}
return count;
}
Utilizarea metodelor
static void Main(string[] args)
{
AccesDate acc = new AccesDate();
Console.WriteLine("Numarul de elemente
inainte de inserare este "
+ acc.NumarInregistrari());
acc.InsertDate();
acc.ActualizeazaDate();
acc.CitireDate();
acc.StergeDate();
acc.AltaCitireDate();
acc.OALtaCitireDate("RO");
Console.ReadKey();
}
Accesul la date în mod deconectat –utilizarea
obiectelor DataSet și SqlDataAdapter
•un obiect DataSet con ține date care sunt păstrate în memorie și elînsuși nu
interacționează cu sursa de date .
•pentru a gestiona conexiunile către sursa de date se utilizează obiecte de tip
SqlDataAdapter, care lucrea zăîmpreună cu obiectul DataSet => pentru popularea
(încărcarea ) cu date a unui obiect DataSet, obiectul SqlDataAdapter realize ază
următoarele opera ții tipice:
–deschide conexiunea
–încarcă datele în obiectul DataSet
–închide conexiunea
•asemănător se întîmplă la actualizarea datelor în cadrul sursei de date pe baza
celor conținuteîn obiectul DataSet:
–deschide conexiunea
–scrie modificările din DataSet în baza de date
–închide conexiunea
Accesul la date în mod deconectat –
exemplu (1)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication2
{
public partial class DateForm : Form
{
private SqlConnection conect;
private SqlDataAdapter daFirme;
private DataSet dsFirme;
private DataGrid dgFirme;
private const string numetab = "Firme";
// initializeaza form -ul cu un DataGrid si un Button
Accesul la date în mod deconectat
–exemplu (2)
public DateForm()
{
Initdata(); // incarca date in DataSet
// creaza si configureaza obiectul DataGrid
dgFirme = new DataGrid();
dgFirme.Location = new Point(5, 5);
dgFirme.Size = new
Size(this.ClientRectangle.Size.Width,this.ClientRectangle.He ight-50);
dgFirme.DataSource = dsFirme;
dgFirme.DataMember = numetab;
// creaza obiectul buton
Button btnUpdate = new Button();
btnUpdate.Text = "Modifica";
btnUpdate.Location = new Point(
this.ClientRectangle.Width / 2 -btnUpdate.Width / 2,
this.ClientRectangle.Height -(btnUpdate.Height + 10));
btnUpdate.Click += new EventHandler(btnUpdateClicked );
// se asigura aparitia controalelor pe form
Controls.AddRange(new Control[] dgFirme, btnUpdate });
}
Accesul la date în mod deconectat
–exemplu (3)
// incarca datele din sursa de date in DataSet
public void Initdata()
{
// instantiaza conexiunea
conect = new SqlConnection
("Data Source=TOSHIBA_DOINA;
Initial Catalog=DBTEST;
Integrated Security=SSPI");
// instantiaza un obiect DataSet // incarca date in DatSet
dsFirme = new DataSet(); daFirme.Fill(dsFirme, numetab);
// instantiaza un obiect 2 SqlDataAdapter }
// cu parametri comanda select si conexiunea
daFirme = new SqlDataAdapter
("select Nume, Tara, Adresa,
NrAngajati from Firme", conect);
// pentru comenzi insert, update si delete
SqlCommandBuilder cmdBldr =
new SqlCommandBuilder(daFirme);
Accesul la date în mod deconectat
–exemplu (4)
public void btnUpdateClicked
(object sender, EventArgs e)
{
// actualizeaza informatiile in baza de da te
daFirme.Update(dsFirme, numetab);
}
}
static class Program
{
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false) ;
Application.Run(new DateForm());
}
}
}
Accesul la date în mod deconectat
–exemplu (5)
PLATFORMA MicroSoft .NET
Generalită ți
•este un cadru de dezvoltare a aplica țiilor software sub care se pot realiza,
distribuiși rula aplica țiile de tip Windows, aplica ții WEBși servicii WEB
•constăîn trei părți principale
–Common Language Runtime ,
–clase pentru platformă
–ASP.NET.
•Microsoft .NET Compact Framework =o infrastructură ajutătoare care
constă dintr -un un set de interfe țe de programare care permite
dezvoltatorilor realizarea de aplica ții pentru dispozitive mobile precum
telefoane inteligente și PDA-uri
•.NET Framework constituie un nivel de abstractizare între aplica țieși
nucleul sistemului de operare (sau alte programe), pentru a asig ura
portabilitatea codului.
•platforma integrează tehnologii care au fost lansate de către Mi crosoft
începând cu mijlocul anilor 90 (COM, DCOM, ActiveX, etc.) cu tehn ologii
actuale (servicii Web, XML).
Componentele platformei
•unelte de dezvoltare -un set de limbaje (C#, Visual Basic .NET, J#,
Managed C++, Objective -C, Python, Smalltalk, Eiffel, Perl, Fortran, Cobol,
Lisp, Haskell, Pascal, RPG, etc), un set de medii de dezvoltare (Visual
Studio .NET, Visio), infr astructura .NET Frame work, o b ibliotecă
cuprinzătoare de clase pentru crearea serviciilor Web (Web Services)2,
aplicațiilor Web (Web Forms) și aplicațiilor Windows (Windows Forms)
•servere specializate -un set de servere Enterprise .NET, continuatoare ale
lui SQL Server 2000, Exchange 2000, BizTalk 2000, etc, care pun la
dispoziție funcționalități diverse pentru stocarea bazelor de date, email,
aplicații B2B3.
•servicii Web -cel mai notabil exeplu este .NET Passport -un mod prin care
utilizatorii se pot autentifica pe site -urile Web vizitate, folosind un singur
numeși o parolă pentru toate . Deși nu este omiprezent, multe aplica ții
webîl folosesc pentru a u șura accesul utilizatorilor.
•dispozitive -dispozitive non –PC, programabile prin .NET Compac t
Framework, o versiu ne redusă a lui .NET Framework: Pocket PC Phone
Edition, Smartphone, Tablet PC, Smart Display, XBox, set -top boxes, etc.
Utilitatea platformei
•aplicațiile distribuite -sunt din ce în ce mai numeroase aplica țiile de tip client /
server sau cele pe mai multe niveluri (numite șin−tier). Tehnologiile distribuite
actuale cer de multe ori o mare afinitate fa ță de producător și prezintă o caren ță
acută a interoperării cu Web -ul. Viziunea actuală se depărtează de cea de tip
client/server către una în care calculatoare, dispozitive inteligente și servicii
conlucrează pentru atingerea scopurilor propuse . Toate acestea se fac deja
folosind standarde Internet neproprietare (HTTP, XML, SOAP).
•dezvoltarea orientată pe componente – este de mult timp cerută simplificarea
integrării componentelor software dezvoltate de diferi ți producători . COM
(Component Object Model) a realizat acest deziderat, dar dezvolt area¸si
distribuirea aplica țiilor COM este prea complexă .Microsoft .NET pune la dispozi ție
un mod mai simplu de a dezvolta și a distribui componente.
•modificări ale paradigmei Web -de-a lungul timpului au fost aduse îmbunătățiri
ale tehnologiilor Web pentru a simplifica dezvoltarea aplica țiilor.În ultimii ani,
dezvoltarea aplica țiilor Web s –a mutat de la prezentare (HTML și alte tehnologii
adiacente) către o capacitate sporită de programare (XMLși SOAP).
•alți factori de maturizare a industriei software – reprezintă con știentizarea
cererilor de interoperabilitate, scalabilitate, disponibilitate; unul din dezideratele
.NET este de a oferi toate acestea.
Arhitectura platformei
Microsoft .NET (1)
Arhitectura platformei
Microsoft .NET (2)
•orice program scris într-unul din limbajele .NET este compilat înMicrosoft
Intermediate Language (MSIL),în concordan ță cuCommon Language Specification
(CLS).Aceste limbaje sunt sprijinite de o bogată colec ție de biblioteci de clase, ce
pun la dispozi ție facilități pentru dezvoltarea de Web Forms ,Windows Forms și
Web Services
•comunicarea dintre aplica țiiși servicii se face pe baza unor clase de manipulare
XML a datelor, c eea ce sprijină dezvoltarea aplica țiilor cu arhitectură pe mai multe
niveluri (n-tier).
•Base Class Library există pentru a asigura func ționalitate de nivel scăzut , precum
operații de I/O, fire de execu ție, lucrul cu șiruri de caractere, comunica ție prin
rețea, etc.; aceste clase sunt reunite sub numele de . NET Framework Class Library ,
ce permite dezvoltarea rapidă a aplica țiilor.
•la baza tuturor se află cea mai importantă componentă a lui .NET Framework –
Common Language Runtime , care răspunde de execu ția fiecărui program .
•nivelul inferior este rezervat sistemului de operare
•Obs. Mediul de dezvoltare Visual Studio .NET nu este absolut nec esar pentru a
dezvolta aplica ții (existăși alternative open -source pentru el), dar datorită
extensibilită ții este cel mai bine adaptat pentru crearea aplica țiilor; de
asemeneacă platforma .NETnu este exclusiv dezvoltată pentru sistemul de
operare Microsoft Windows, ci și pentru anumite tipuri de Unix (FreeBSD sau
Linux).
Componente ale lui .NET Framework
Microsoft Intermediate Language
•ingineria software => abstractizarea
•în cazul limbajelor de programare, s -a ajuns treptat la crearea unor nivele de
abstractizare a codului rezultat la compilare, precum p-code(cel produs de
compilatorul Pascal -P)șibytecode (în cazul limbajului Java).
•bytecode-ul Java, generat prin compilarea unui fi șier sursă, este cod scris într-un
limbaj intermediar care suportă programarea orientată pe obiecte ; bytecode -ul
esteîn același timp o abstractizare care permite executarea codului Java,
indiferent de platforma țintă, atâta timp cât această platformă are implementată o
mașină virtuală Java capabilă să “traducă”mai departe fi șierul class în cod nativ.
•Microsoft a realizat și el propria sa abstractizare de limbaj, aceasta numindu -se
Common Intermediate Language ; astfel, de și există mai multe limbaje de
programare de nivel înalt (C#, Managed C++, Visual Basic .NET, etc), la compilare
toate vor produce cod în același limbaj intermediar: Microsoft Intermediate
Language (MSIL, sau IL pe scurt)
•asemănător cu bytecod -ul Java,IL are capabilită ți de programare orientată pe
obiecte, precum abstractizarea datelor, mo ștenirea, polimorfismul, și include
concepte care s -au dovedit a fi extrem de necesare, precum excep țiile sau
evenimentele; aceas tă abstractizare de limbaj permite rularea aplica țiilor
independent de platformă (cu aceea și condiție ca la Java: să existe o ma șină
virtuală pentru acea platformă ).
Common Language Specification (CLS)
•unul din scopurile .NET este de a sprijini integrarea limbajelor astfelîncât
programele, de și scriseîn diferite limbaje, să poată inter -opera, folosind din plin
moștenirea, polimorfismul, încapsularea, excep țiile, etc.
•dar limbajele utilizate nu sunt identice: u nele suportă supra încărcarea operatorilor
(de exemplu Managed C++, C#), altele nu (Visual Basic .NET); une le suntcase
sensitive, altele nu.
•pentru a se asigura totu și interoperabilitatea codului scris în diferite limbaje,
Microsoft a publicat Common Language Specification (CLS), un subset al lui CTS
(Common Type System ), conținînd specifica ții de reguli necesare pentru integrarea
limbajelor
•CLS define ște un set de reguli pentru compilatoarele .NET, asigurând faptul că
fiecare compilator va genera cod care interferează cu platforma (mai exact, cu
CLR–ul)într-un mod independent de limbajul sursă .
•=> obiectele și tipurile create în diferite limbaje pot interac ționa fără probleme de
compatibilitate. combina ția CTS/CLS asigură de fapt inter -operarea limbajelor: se
poate ca o clasă scrisă în C# să fie mo ștenită de o clasă scrisă în Visual Basic care
aruncă excep ții ce sunt prinse de cod scris în C++ sau J#.
Common Language Runtime (CLR)
•CLR este cea mai importantă parte componentă a lui .NET Framework
•este responsabil cu managementul și execuția codului scris în limbaje .NET, aflat în
format IL ( Intermmediate Language );
•este foarte similar cu Java Virtual Machine
•CLR instan țiază obiectele , face verificări de securitate , depune obiectele în
memorie, dispon ibilizează memoria prin mecanismul de colectare de de șeuri
(garbage collection ).
•ín urma compilării unei aplica ții rezultă un fi șier cu extensia .exe dar care nu este
un executabil portabil Windows, ci un executabil portabil .NET ( .NET PE); acest cod
nu este deci un executabil nativ, ci se va rula de către CLR ,întocmai cum un fi șier
class este rulat în cadrul JVM ( Java Virtual Machine ).
•CLR folose ște tehnologia compilării JIT (Just In Time )-o implementare de ma șină
virtuală,în care o metodă sau o func ție,în momentul în care este apelată pentru
prima oară , este tradusă în cod mașină. Codul translatat este depus într-un cache,
evitând-se astfel recompilarea ulterioară
Tipuri de complilatoare JIT
•există3 tipuri de compilatoare JIT:
–NormalJIT–care acționeazăîn conformitate cu descrierea de mai sus.
–Pre-JIT- compilează întregul cod în cod nativ singură dată .În mod
normal este folosit la instalări .
–Econo-JIT-se folosește pe dispozitive cu resurse limitate. Compilează
codul IL bit cu bit, eliberând resursele folosite de codul nativ ce este
stocatîn cache.
•în esență, activitatea unui compilator JIT este destinată
îmbunătățirii performan ței execuției, ca alternativă la compilarea
repetată a aceleia și bucăți de codîn cazul unor apelări multiple
•unul din avantajele mecanismului JIT apare în clipaîn care codul, o
dată ce a fost compilat , se execută pe diverse procesoare ; dacă
mașina virtuală este bine adaptată la noua platformă , atunci acest
cod va beneficia de toate optimizările posibile ,fără a mai fi nevoie
recompilarea lui.
Common Type System
•toate limbajele care fac parte din pleiada .NET trebuie să aibă un set
comun de concepte pentru a putea fi integrate: pentru a asigura
interoperabilitatea limbajelor din .NET Framework, o c lasă scrisă în C#
trebuie să fie echivalentă cu una scrisă în VB.NET, o interfa ță scrisăîn
Managed C++ treb uie să fie perfect utilizabilă în Managed Cobol.
•Common Type System (CTS) asigură faptul că orice limbaj trebuie să
recunoască și să poată manipula ni ște tipuri comune
Tipuri comune în CTS (1)
•Tipuri valoare
–reprezintă tipuri alocate pe stivă și nu pot avea valoare de null.
–includ tipurile primitive, structuri și enumerări .
–datorită faptului că de regulă au dimensiuni mici si sunt alocat e
pe stivă, se manipuleaza eficient, reducând overhead -ul cerut de
mecanismul de colectare a de șeurilor (garbage collection ).
•Tipuri referin ță
–se folosește dacă variabilele de un anumit tip cer resurse de
memorie semnificative.
–variabilele de tip referin ță conțin adrese de memorie heap și
pot fi null.
–transferul parametrilor se face rapid, dar referin țele induc un
cost suplimentar datorită mecanismului de colectare de de șeuri.
Tipuri comune în CTS (2)
Boxingși unboxing
•motivul pentru care există tipuri primitive este acela și cașiîn Java: performan ța.
Însă orice variabilă în .NET este compatibilă cu clasa Object ,rădăcina ierarhiei
existente în .NET. De exemplu, inteste un alias pentru System.Int32 , care se
derivează din System.ValueType .
•tipurile valoare se stochează pe stivă , dar pot fi oricând convertite într-un tip
referință memorat în heap; acest mecanism se nume ște boxing:
int i = 1; //i-un tip valoare
object box = i; //box-un obiect referinta
•când se face conversie de tip boxing, se obține un obiect care poate fi gestionat la
fel ca oricare altul, făcându–se abstrac ție de originea lui. Inversa boxing-ului este
unboxing-ul, prin care se poate converti un obiect în tipul valoare echivalent, ca
mai jos:
int j = (int)box;
unde operatorul de conversie ( cast) este suficient pentru a converti de la un
obiect la o variabilă de tip valoare .
Tipuri comune în CTS (3)
•Clase, prop rietăți, indexatori – platforma .NETsuportă pe deplin
programarea orientată pe obiecte , concepte legate de obiecte
(încapsularea, mo ștenirea, polimo rfismul) sau t răsături legate de
clase (metode, c împuri, membri statici, vizibilitate, accesibilitate,
etc); de asemenea sunt incluse elemente precum proprietă ți,
elemente de indexare și evenimente.
•Interfețe- reprezintă acela și concept precum clasele abstracte din
C++ (dar con ținând doar func ții virtuale pure), sau interfe țele Java.
O clasă care derivă dintr -o interfață trebuie să implementeze toate
metodele acelei interfe țe.Se permite implementarea simultană a
mai multor interfe țe (în rest mo ștenirea claselor este simplă ).
•Delegați-inspirați de pointerii la func ții din C,ce permit
programarea generică . Reprezintă versiunea “sigură” a pointerilor
către func ții din C/C++ și sunt mecanismul prin care se tratează
evenimentele.
Metadate și atribute
•metadatele confirmă verificarea tipurilor care este înglobată în instrumentul Common
Language Runtime CLR care,în sine, reprezintă o parte a sistemului de securitate .
•sunt utilizate de instrumentul CLR pentru a determina necesită țile fiecărui tip precum și
contextul în care trebuie să ruleze un anumit obiect : atunci cînd un ansamblu este
compilat, compila torul adaugă într-o parte a acestuia numită manifest , o listă a
ansamblurilor pe care programul le va folosi.
•instrucțiunile din limbajul intermediar care alcătuiesc tipurile , descriu exact membri
celorlalte tipuri pe care le apelează ; MicroSoft a definit specifica țiile metadatelor astfel
încît să acopere tot ce este necesar pentru definirea completă a unu i tip. De asemenea ,
este permisă extinderea metadatelor predefinite prin a șa numitele atribute particularizate.
•metadata înseamnă în general “date despre date ”;în cazul .NET, reprezintă informa ții
destinate a fi citite de către ma șină, nu de către utilizatorul uman .
•metadatele sunt stocate împreună cu codul pe care îl descriu; pe baza metadatelor, CLR
știe cum să instan țieze obiectele, cu m să le apeleze metodele , cum să acceseze
proprietă țile. Prin mecanismul numit reflection , o aplicație (nu neapărat CLR ) poate să
interogheze aceaste metadate și să afle ce expune un obiect .
•metadatele con țin o declara ție a fiecărui tip și câte o declara ție pentru fiecare metodă ,
câmp, proprietate, eveniment al tipului respectiv; pentru fiecar e metodă implementată ,
metadatele con țin informa ții care permit încărcătorului clasei respective să localizeze
corpul metodei.
•de asemena mai pot con ține declara ții despre cultura aplica ției respective, a dică despre
localizarea ei (limba folo sităîn partea de interfa ță utilizator ). Mecanismul prin care aceste
informații se folosesc pe parcursul rulării de către aplica ții se nume ștereflection .
Ansamble ( assemblies )
•Un ansamblu ( assembly) reprezintă un bloc func țional al unei aplica ții .NET.
•formează unitatea fundamentală de distribuire , versionare, reutilizare și permisiuni de
securitate. La execu ție (runtime),un tip de date există în interiorul unui ansamblu ( și nu
poate exista în exteriorul acestuia).
•conține tipuri, deci include și metadate ce descriu tipurile respective și care sunt folosite de
către CLR . Scopul acestor ansambluri este să se asigure dezvoltarea softului în modplug-and-
play. Metadatele nu sunt suficiente pentru acest lucru :manifestele .
•unmanifest reprezintă metadate despre ansamblul care găzduie ște tipurile de date. Con ține
numele ansamblului, informa ția despre versiune, referiri la alte ansamble, o lis tă a tipurilor
acestora, permisiuni de securitate și altele.
•identitatea unui ansamblu se compune dintr -o serie de elemente precum: numele
ansamblului, versiune, cultura, precum și un nume sugestiv ; un nume sugestiv este o cheie
publică care împreună cu cheia privată a celui care publică ansamblul este uti lizată pentru
semnarea și identificarea ansamblului. Un ansamblu care este împărțitîntre mai multe
aplicații are de asemenea un nume ( shared name ).
•deoarece un ansamblu con ține date care îl descriu, instalarea lui poate fi făcută copiind
ansamblul în directorul destina ție dorit. Când se dore ște rularea unei aplica ții conținuteîn
ansamblu, manifestul va instrui mediul .NET despre modulele care sunt conținuteîn
ansamblu. Sunt folosite de asemenea și referințele către orice ansamblu extern de care are
nevoie aplica ția.
Structura unui ansamblu
Nume ansamblu
Versiune
Cultura
Sistem de operare și procesor
Nume sugestiv (op țional)
Cheie public ă
Cod hash fi șier cu manifestul semnat cu cheie privată
Fișiere în ansamblu:
Nume fi șier / cod hash fișier
Ansambluri referen țiate
Nume ansamblu / informa ții ansamblu
Ansamblele, manifestele și
versionarea
•atunci cînd se utilizează într-un ansamblu un tip definit în cadrul altui ansamblu,
compilatorul crează o legătură statică spre ansamblul respectiv , manifestul
conținînd o lista a tuturor ansamblurilor cu care ansamblul curent este legat static
și care permite sistemului să încarce ansamblul corect în momentul execu ției.
•orice ansamblu are legătură cu ansamblul mscorlib , deoarece acesta con ține toate
tipurile de bază utilizate într-un program .NET.
•Assembly cache este un director aflat în mod normal în directorul
\Winnt\Assemblies . Atunci când un ansamblu este instalat pe o ma șină, el va fi
adăugatînassembly cache . Dacă un ansamblu este descărcat de pe Internet , el va
fi stocatîın acestassembly cache ,îıntr-o zonă tranzientă . Aplicațiile instalate vor
avea assemblies într-un assembly cache global. În acestassembly cache vor exista
versiuni multiple ale aceluia și ansamblu. Dacă programul de instalare este scris
corect, va evita suprascrierea ansamblelor deja existente ( și care func ționează
perfect cu aplica țiile instalate), a dăugând doar noul ansamblu .
•CLR este cel care decide, pe baza informa țiilor din manifest, car e este versiunea
corectă de ansamblu de care o aplica ție are nevoie.
Tipuri deaplicație
GUI (Windows)
•- utilizează /t:winexe
•-definește o clasă cu o metodă Main ()
•- utilizează clase System .Windows.Forms
Consolă
•- utilizează /t:exe
•-definește o clasă cu o metodă Main ()
Servicii NT
•- utilizează /t:winexe
•- utilizează clase
•System.ServiceProcess.ServiceBase
ASP .NET
•- utilizează /t:library
•- utilizează clase System ..Web.UI
Servicii web
•- utilizează /t:library
•- utilizează clase System ..Web.Services
•Bibliotecă
•- utilizează /t:libraryTip aplica țieObserva ții
GUI
(Windows)- utilizează /t:winexe
-define ște o clasă cu o metodă Main()
– utilizează clase System.Windows.Forms
Consolă – utilizează /t:exe
-define ște o clasă cu o metodă Main()
Servicii NT – utilizează /t:winexe
– utilizează clase
System.ServiceProcess.ServiceBase
ASP .NET – utilizează /t:library
– utilizează clase System..Web.UI
Servicii web – utilizează /t:library
– utilizează clase System..Web.Services
Bibliotecă – utilizează /t:library
Colectarea de de șeuri
(garbage collection )
•managementul memoriei este una din sarcinile cele mai consumatoa re de
resurse.
•colectarea de de șeuri (garbage collection ) reprezintă mecanismul care se
declanșează atunci când alocatorul de memorie răspunde negativ la o
cerere de alocare de memorie.
•implementarea este de tip mark and sweep : se presupune ini țial că toată
memoria alocată se poate disponibiliza , după care se determină care din
obiecte sunt referite de variabilele aplica ției; cele care nu mai sunt
referite sunt dealocate, celelalte zone de memorie sunt compacta te.
•obiectele a căror dimensiune de memorie este mai mare decât un a numit
prag nu mai sunt mutate, pentru a nu cre ște semnificativ penalizarea de
performan ță.
•în general , CLR este cel care se ocupă de apelarea mecanismului de
colectare a de șeurilor; totu și, la dorin ță, programatorul poate cere rularea
lui.
Avantaje ale platformei .NET (1)
•dezvoltarea multilimbaj – deoarece există mai multe limbaje pentru această
platformă , este mai u șor de implementat păr ți specifice ale unei aplica țiiîn
limbajele cele mai adecvate. Numarul limbajelor curent implement ate este mai
mare decât 10. Această dezvoltare are în vedere și depanarea aplica țiilor
dezvoltate în mai multe limbaje
•independen ța de procesor și de platformă – limbajul intermediar IL este
independent de procesor. O da tă scrisăși compilată , orice aplica ție .NET (al cărei
management este făcut de către CLR ) poate fi rulată pe orice platformă . Datorită
CLR-ului, aplica ția este izolată de particularită țile hardware sau ale sistemului de
operare.
•managementul automat al memoriei -problemele de tipul memory leakage nu
mai trebuie să preocupe programatorii ;overhead -ul indus de către mecanismul de
colectare de de șeuri este suportabil, fiind implementat în sisteme mult mai
timpurii.
•suportul pentru versionare -ca o lecțieînvățată din perioada de DLL-urilor,
versionarea este acum un aspect de care se ține cont. D acă o aplica ție a fost
dezvoltată și testată folosind anumite componente , instalarea unei componente
de versiune mai nouă nu va atenta la buna func ționare a aplica țieiîn discuție: cele
două versiuni vor coexista pa șnic, alegerea lor fiind făcută pe baza manifestelor .
Avantaje ale platformei .NET (2)
•sprijinirea standardelor deschise – nu toate dispozitivele rulează sisteme de
operare Microsoft sau folosesc procesoare Intel. Din a ceastă cauză orice este
strâns legat de acestea este evitat. Se folose ște XMLși cel mai vizibil descendent al
acestuia, SOAP. Deoarece SOAP este un protocol simplu, bazat pe text, foarte
asemănător cu HTTP 5, el poate trece u șor de
firewall-uri, spre deosebire de DCOM sau CORBA.
•distribuirea u șoară-actualmente instalarea unei aplica ții sub Windows înseamnă
copierea unor fi șiereîn niște directoare anume, modificarea unor valori în regiștri,
instalare de componente COM, etc. Aplica țiile .NET, datorită metadatelor și
mecanismului reflection trec de aceste probleme. Se dore ște ca instalarea unei
aplicații să nuînsemne mai mult decât copierea fi șierelor necesare într-un
director, iar dezinstalarea aplica ției să se facă prin ștergerea acelui director.
Avantaje ale platformei .NET (3)
•arhitectură distribuită -noua filosofie este de a asigura accesul la servicii Web
distribuite; acestea co nlucrează la ob ținerea informa ției dorite. P latforma .NET
asigură suport și unelte pentru realizarea acestui tip de aplica ții.
•interoperabilitate cu codul unmanaged -codulunmanaged se referă la cod care
nu se află în totalitate sub controlul CLR. El este rulat de CLR, dar nu ben eficiază de
CTS sau colectare de de șeuri. Este vorba de apelurile func țiilor din DLL -uri,
folosirea componentelor COM, sau fol osirea de către o componentă COM a unei
componente .NET. Codul existent se poate folosi în continuare.
•securitate -aplicațiile bazate pe componente distribuite cer automat securitate.
Modalitatea actuală de securizare , bazată pe drepturile contului utilizatorului , sau
cel din Java, în care codul suspectat este rulat într-unsandbox,fără acces la
resursele critice este înlocuitîn .NET de un control mai fin, pe baza metadatelor
din ansamble (zona din care provine -ex. Internet, intranet, ma șina locală , etc)
precumși a politicilor de securitate care se pot seta .
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Paradigme de programare [626448] (ID: 626448)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
