-descrie valoarea unei proprietati.
Daca utilizati si alte tag-uri decat cele recomandate,documentatia va
trebui sa contina si explicatia acestor tag-uri,pentru ca utilizatorul sa
le poata exploata eficient.Fila de documentare poate sa contina informatii
despre: clase,interfete,delegati,membrii clasei,evenimente,metode si
proprietati,tipuri de data definite de utilizator...etc.
Pentru ca fila de documentare sa poata fi citita cu utilitarele de tip
IntelliSense,trebuie ca numele filei .xml sa fie acelasi cu cel al filei
de asamblare (identic cu executabilul dar cu extensie diferita).
Fila de documentare este optionala,dar este recomandabila atunci cand
oferiti aplicatii ce pot fi transformate,adaptate,modernizate...etc.
-67-
STRUCTURA SI EXECUTIA APLICATIILOR
O aplicatie C# completa,include cateva module executabile,cateva file
de resurse si una sau mai multe biblioteci DLL.Cu cat programul este mai
complex,cu atat este bine sa fie fragmentat in module mai mici de memorie
ce pot fi incarcate si executate mult mai rapid.Incarcarea acestor file
in memorie,si apoi eliberarea lor,se face automat,cu ajutorul unor functii
speciale.
In mediul real de lucru,majoritatea utilizatorilor vor executa o astfel
de aplicatie in paralel cu inca una sau mai multe aplicatii similare.Ca
rezultat,memoria va fi incarcata cu un amalgam de file si resurse de la
toate aplicatiile aflate in curs de executie.Mai mult decat atat,este
posibil ca doua sau mai multe aplicatii sa utilizeze aceeasi biblioteca
DLL.Daca una dintre aplicatii elibereaza memoria,fila va fi eliberata din
memorie si va bloca executia celorlalte aplicatii.Pentru a evita astfel de
situatii,si pentru a organiza putin spatiul de memorie si ordinea de
executie,este necesar ca toate datele unei aplicatii sa fie izolate de
cele ale altor aplicatii.
APPLICATION DOMAIN
O metoda foarte flexibila si sigura de a "impacheta" toate datele unei
aplicatii o prezinta clasa AppDomain,creata special pentru acest scop.In
interiorul unei astfel de clase,fiecare aplicatie va putea fi executata
in memorie,intr-un spatiu izolat,ce nu interfereaza cu alte aplicatii
aflate in executie concomitent.Clasa prezinta o serie de metode speciale,
ce permit incarcarea modulelor executabile si respectiv eliberarea
memoriei,dupa algoritmi stabiliti prin linii de program.Cu alte cuvinte,
intr-o astfel de clasa,modulele executabile pot fi incarcate si executate
in ordinea dorita,dupa care memoria poate fi eliberata imediat,fara a mai
astepta mecanismul automat de "garbagge".Acest avantaj este evident mai
ales atunci cand se apeleaza o functie dintr-o biblioteca DLL de proportii
mari.In mod normal,biblioteca se incarca in memorie,se executa functia si
apoi fila paraziteaza memoria pana cand este identificata si eliberata de
mecanismul automat.Daca se utilizeaza o clasa AppDomain,functia dorita
poate fi inclusa intr-un modul executabil mic,ce se incarca in memorie
doar in momentul dorit,se executa functia,dupa care se elibereaza imediat
memoria,pentru operatiile urmatoare.Aceasta economie de memorie pare sa
fie nesemnificativa la prima vedere,dar daca se ia in considerare faptul
ca in mediu de retea exista simultan milioane de utilizatori care apeleaza
astfel de aplicatii,diferenta este mai mult decat semnificativa.Un concept
bun,poate elimina zeci de secunde de asteptare inutila,la fiecare executie
a programului.Principiul de functionare cuprinde trei etape:
1. se creaza o instanta a clasei cu App.Domain.CreateDomain()
2. se incarca si se executa modulul dorit cu ExecuteAssembley()
3. se elibereaza memoria imediat dupa executie cu AppDomain.Unload()
Mai mult decat atat,se poate evita si incarcarea bibliotectii DLL
System,daca apelul functiilor se face specificand si fila sursa ( fila
sursa pentru clasele din System se incarca default).
EXEMPLU: in loc de: Console.WriteLine(....)
se poate utiliza: System.Console.WriteLine(...)
-68-
EXEMPLU:
class Test {
static void Main() {
long mem1.mem2,mem3;
mem1 = System.GC.GetTotalMemory(false);
System.AppDomain dom1 =
System.AppDomain.CreateDomain("Domeniul1")';
dom1.ExecuteAssembley(@"c:\v3\Form1.exe");
System.AppDomain dom2 =
System.AppDomain.CreateDomain("Domeniul2");
dom1.ExecuteAssembley(@"c:\v3\Form2.exe");
mem2 = System.GC.GetTotalMemory(false);
System.Console.WriteLine("Memoria initiala = {0:F} bytes",mem1);
System.Console.WriteLine("Memoria dupa alocare: {0:F} bytes",mem2);
System.AppDomain.Unload(dom1);
System.AppDomain.Unload(dom2);
mem3 = System.GC.GetTotalMemory(false);
mem1 = mem2-mem3;
System.Console.WriteLine("Dupa eliberarea memoriei: {0:F}",mem3);
System.Console.WriteLine("Memoria eliberata= {0:F} bytes",mem1);
System.Console.ReadLine();
}}
Salvati fila cu numele Domain1.cs si compilati.
In exemplul de mai sus se pot remarca urmatoarele:
1. Biblioteca System nu este importata static si fiecare clasa este
apelata cu numele complet: System....
2. Se creaza doua obiecte de tip AppDomain.In fiecare astfel de obiect
se incarca si se executa cate un modul executabil,preluat de la o adresa
locala: c:\v3 (in exemplu v3 este un director local).
3. Se contorizeaza memoria totala ocupata in Garbagge Collector,inainte
si dupa eliberarea modulelor.
4. In timpul executiei,inchideti cele doua ferestre deschise automat,
pentru a permite continuarea executiei,apoi evaluati consumul de memorie.
Fiecare modul poate fi incarcat si descarcat independent,in momentul
dorit.La un calcul sumar,puteti observa ca memoria ocupata este mult mai
mare decat dimensiunea stricta a modulului.Ca rezultat,prin eliberarea
clasei AppDomain se elibereaza mai multa memorie decat volumul modulului.
Pentru orice alt gen de operatii cu si asupra modulelor,studiati cu
atentie metodele clasei AppDomain.
In concluzie,obiectele AppDomain prezinta urmatoarele avantaje:
1.-o eroare intervenita intr-o aplicatie nu poate afecta executia altor
aplicatii simultane.
2.-se exclude suprascrierea accidentala a unor resurse,de catre functii
executate intr-o aplicatie concomitenta
3.-fiecare aplicatie poate fi incarcata si executata in momentul dorit
4.-se poate controla exact consumul de memorie.
5.-se impiedeca accesul altor utilizatori din retea la datele din
aplicatie,chiar daca partajeaza acelasi spatiu de memorie cu utilizatorul
6.-un singur proces poate executa secvente de module executabile,in
conditii de maxima securitate in executie.
7.-creste flexibilitatea de lucru a serverului de retea
-69-
ATRIBUTELE C SHARP
Atributele sunt un mijloc eficient pentru a putea asocia comenzi C#
cu anumite fragmente de cod din program (clase,metode,proprietati etc.).
Atributele se utilizeza pentru a adauga in program metadate,adica niste
informatii suplimentare pentru compilator sau pentru descrierea mai ampla
a unor date din program.Sunt asemanatoare cu directivele de precompilare,
dar sunt mult mai maleabile,deoarece pot fi asociate doar unor fragmente
mici de cod,fara sa influenteze intreaga aplicatie.O data incluse in cod,
atributele pot fi apelate in timpul executiei,printr-un procedeu denumit
"Reflectie" (Reflection) utilizand biblioteca System.Reflection.
Pentru a introduce un atribut,se utilizeaza paranteze drepte.Numele
atributului se introduce intre paranteze drepte,in fata declaratiei cu
care urmeaza sa fie asociat.Prin conventie,numele atributelor se termina
cu "Attribute" pentru a fi cat mai usor de recunoscut in etapa de depanare
a programelor.
EXEMPLU: [SerializableAttribute]
class ClasaMea {...}
In exemplul de mai sus,atributul SerializableAttribute va fi asociat
in etapa ce compilare cu clasa ClasaMea.
Se pot declara si atribute formate din mai multi parametri,separati
intre ei prin virgula.Daca fiecare parametru are un nume distinct,pot fi
introdusi in orice ordine.Daca exista si parametri pozitionali,acestia
trebuie sa fie introdusi intr-o anumita ordine.
EXEMPLU:
[DllImport("user32.dll,SetLastError=false,ExactSpelling=false)]
In atributul de mai sus,user32.dll este pozitional si trebuie neaparat
sa fie primul parametru din atribut,in timp ce urmatorii doi au un nume
distinct si pot fi introdusi in orice ordine.
Un atribut asociaza un set oarecare de date predefinite,cu un fragment
oarecare de cod (un bloc de date).Acest bloc de date,poate fi: un modul
executabil intreg,o clasa,o metoda,un tip de data,un eveniment,o interfata
sau un delegat,o valoare returnata,o proprietate sau chiar un alt atribut.
Pentru declararea atributelor se poate utiliza clasa Attribute si membrii
sai.Metadatele introduse prin atribute pot influenta modul de executie
runtime a programului,sau pot afecta modul in care este procesata intreaga
aplicatie.Unele limbaje de programare folosesc acest procedeu pentru a
introduce in program date ce nu sunt implementate in platforma .Net,dar
sunt predefinite in alte resurse din sistem.
Nu este obligatoriu,dar este comod sa declarati un atribut nou cu
ajutorul unei clase Attribute.
EXEMPLU:
[System.AttributeUsage(System.AttributeTargets.Class |
System.Attributetargets.Struct) ]
public class Author : System.Attribute { }
Prin acest mecanism,clasa ce asociaza atributul,mosteneste si toate
metodele clasei Attribute,iar compilatorul va identifica mult mai usor si
mai rapid metadatele din atribut.
Exista si situatii in care asocierea dintre atribut si coduri poate
fi interpretata ambiguu.
-70-
EXEMPLU: [AtributulMeu]
int Metoda() { return 0; }
In exemplul de mai sus,se poate interpreta asocierea atributului fie cu
Metoda(),fie cu valoarea returnata prin return.In mod normal asocierea
se face cu Metoda(),dar pentru a elimina orice suspiciune se pot utiliza
formule explicite.
EXEMPLU: [method: AtributulMeu]
int Metoda() { return 0; }
sau [return: AtributulMeu]
int Metoda() { return 0; }
Atributele se utilizeaza frecvent in urmatoarele situatii:
1.Atribute conditionale prin care se controleaza fluxul de executie:
EXEMPLU: #define TRACE_ON
using System;
using System.Diagnostics;
public class Trace {
[Conditional("TRACE_ON")]
public static void Msg(string msg)
{ Console.WriteLine(msg); }}
public class ProgramClass {
static void Main(){
Trace.Msg("Se executa functia conditionala !");
Console.ReadLine();
}}
Salvati fila cu numele Atribut1.cs si compilati.
In exemplul de mai sus,Atributul conditional este asociat cu functia
Trace si verifica daca TRACE_ON este definita in program.Pentru a putea
observa diferenta,eliminati directiva de precompilare si apoi compilati
din nou modulul.Acest mecanism poate fi utilizat cu succes in etapa de
depanare a unui program,pentru a verifica daca o variabila oarecare are
sau nu are vizibiliate intr-un anumit spatiu de memorie.Daca se utilizeaza
mai multe atribute simultan,functia va fi executata daca se verifica
oricare dintre ele:
Exemplu: [Conditional("A"),Conditional{"B")]
introduce conditia ca A sau B sa fie definit in memorie
2.Atribute pentru actualizarea aplicatiilor (declara datele obsolete)
EXEMPLU: using System;
[System.Obsolete("A fost inlocuita cu clasa B")]
class A{ public void Metoda() {} }
class B{ [System.Obsolete("Folositi MetodaNoua !",true)]
public void MetodaVeche() {}
public void MetodaNoua() {}
}
class Test{ static void Main(){ A a = new A();
B b = new B();
b.MetodaNoua();
b.MetodaVeche();
}}
Salvati fila cu numele Atribut2.cs si compilati.
Observati ca se returneaza o eroare de compilare si doua avertismente.
-71-
Primul atribut introduce doar un avertisment,iar cel de al doilea
introduce o eroare,prin parametrul "true".Pentru a putea compila acest
modul,exista urmatoarele variante:
1. renuntati la argumente si pastrati datele perimate
2. renuntati la clasa A si la functia MetodaVeche (declarate perimate)
3. pastrati datele perimate dar fara sa apelati clasa sau metoda.
3.Atribute globale prin care se declara metadate valabile pentru intregul
modul.Acest gen de metadate specifica de obicei versiunea,autorul si
firma,drepturile de autor si descrierea tipului de aplicatie.
EXEMPLU: using System;
using System.Reflection;
[assembley: AssembleyVersion("1.0.0.0")]
[assembley: AssembleyTitle("AplicatiaMea")]
[assembley: AssembleyDescription("Mesaj tip Hello World")]
[assembley: AssembleyConfiguration("Configuratie comuna")]
[assembley: AssembleyCompany("Compania Mea")]
[assembley: AssembleyProduct("Aplicatie Test")]
[assembley: AssembleyCopyright("Open source")]
[assembley: AssembleyTrademark("Nu este patentata")]
class Test { static void Main(){
Console.WriteLine("Hello World !");
Console.ReadLine();
}}
Salvati fila cu numele Atribut3.cs si compilati.Metadatele pot fi
consultate cu ildasm.exe in MANIFEST (vezi si numele filei Atribut3.exe)
Pentru a controla modul de utilizare a atributelor se poate apela la
clasa AttributeUsage.
EXEMPLU:
using System;
[AttributeUsage(System.AttributeTargets.Class, AllowMultiple=true)]
class A3: System.Attribute{}
[A3,A3,A3]
class ClasaDerivata{}
public class TestAtribute {
static void Main() {
ClasaDerivata d = new ClasaDerivata();
Console.WriteLine("Atributele clasei derivate sunt: ");
object[] attrs = d.GetType().GetCustomAttributes(true);
foreach(Attribute attr in attrs)
{ Console.WriteLine(attr); }
Console.ReadLine();
}}
Salvati fila cu numele Argument4.cs si compilati.In acest exemplu prin
argument se specifica faptul ca in clasele mostenitoare ale clasei A3 se
pot evalua argumente multiple identice.Pentru a sesiza diferenta,compilati
modulul fara atributul clasei A3.
In sinteza,atributele permit controlul fluxului de executie,sau
introduc metadate in program (asociate unui anumit bloc de date).
-72-
Containere de tip Collection
Obiectele de tip container au rostul de a separa anumite grupuri de
date,in spatii cu vizibilitate rezervata.Colectiile sunt un tip special
de containere ce implementeaza si interfata System.Collections.IEnumerable
prin care se genereaza un obiect denumit "enumerator" cu rostul de a putea
naviga intr-un grup de date de acelasi fel.Obiectele de tip colectie,nu
numai ca grupeza date de acelasi tip,dar permit si o serie intreaga de
operatii automate de filtrare,selectare sau sortare a datelor.Obiectele
de tip colectie sunt indispensable atunci cand trebuie facuta legatura
dintre codurile executabile si file de resurse de tip lista,tabel,baza
de date,file XML etc.
Programarea cu obiecte de tip colectie nu este o inovatie a limbajului
C#.Primele obiecte de acest gen au fost stivele simple si dateaza inca
din epoca de pionierat a tehnicii de calcul.Platforma .Net a introdus in
prima etapa,doar obiecte tipizate,de tip stiva,lista sau tabel incrucisat
(hash tables).Ulterior,s-au introdus si colectiile de tip generic,ce
implementeaza una sau mai multe interfete de tip ICollection,IComparer,
IEnumerable,IList,IDictionary sau IDictionaryEnumerator cu scopul de a
dezvolta facilitati noi,cat mai versatile.Obiectele standard de tip
colectie sunt arhivate in System.Collections si System.Collections.Generic
si permit operatii complexe de organizare a grupurilor de date.Cele de
tip generic,sunt mai noi,mai complexe si mai bine structurate,iar cele
tipizate sunt mai simple si mai directe.Alegerea obiectului potrivit se
va face in functie de necesitatile din program.Cel mai simplu obiect de
acest gen,este stiva simpla.Cu un astfel de obiect,elementele unui grup
de date pot fi indexate,sortare,prelucrate independent sau in grup.
EXEMPLU:
using System;
using System.Collections;
public class StivaTest {
public static void Main() {
Queue stiva1 = new Queue();
stiva1.Enqueue("Primul element");
stiva1.Enqueue("Al doilea element");
stiva1.Enqueue("Al treilea element");
Console.WriteLine("Stiva contine valorile: ");
Console.WriteLine("Numar= {0}",stiva1.Count);
Console.WriteLine("Valori=");
Editeaza(stiva1);
Console.ReadLine();
}
public static void Editeaza( IEnumerable colectie1) {
foreach ( Object obj in colectie1 )
Console.WriteLine(" {0}",obj);
}}
Salvati fila cu numele Stiva1.cs si compilati.
Obiectele de tip stiva,sunt rudimentare dar ocupa foarte putina
memorie.Sunt de preferat ori de cate ori sunt necesare doar operatii
simple,fara rearanjarea elementelor in memorie.
EXEMPLE: memorarea unei parole,setari,coduri de acces etc.
-73-
Pentru operatii mai complexe,se pot utiliza obiecte de tip ArrayList,
sau corespondentul lor de tip generic,reprezentat prin obiectele de tip
List.Aceste obiecte au un set bogat de metode,prin care se pot face
operatii automate de sortare sau rearanjare a elementelor,dupa un anumit
algoritm.Cea mai frecventa utilizare,este pentru a prelua date dintr-o
resursa,pentru a le transfera apoi spre un obiect vizual de prezentare
sau prelucrare a lor (Exemplu: dintr-un tabel intr-un ComboBox).
EXEMPLU:
Creati un fisier de tip text,denumit Fructe.txt in care arhivati o
lista de fructe si pretul sau cantitatea lor:
mere 200 kg 3 lei/kg
cirese 130 kg 7 lei/kg
struguri 200 kg 9 lei/kg
Salvati fisierul pe unitatea C: si apoi editati un modul de genul:
using System;
using System.IO;
using System.Collections;
public class ExempluSortare {
public static void Main() {
ArrayList aria1 = new ArrayList();
string path = @"c:\Fructe.txt";
string[] readText = File.ReadAllLines(path);
foreach (string s in readText) { aria1.Add(s); }
aria1.Sort(0,aria1.Count,null);
Console.WriteLine("Datele preluate sunt: ");
Console.WriteLine("Numar: {0}", aria1.ount);
Console.WriteLine("Capacitate: {0}", aria1.Capacity);
Console.WriteLine("Valori:");
Editeaza(aria1);
Console.ReadLine();
}
public static void Editeaza ( IEnumarable lista1 ) {
foreach ( Object obj in lista1 )
Console.WriteLine(" {0}", obj);
}}
Salvati fila cu numele ArrayList1.cs si compilati.
Exemplul de mai sus,nu numai ca citeste datele din resursa,dar le si
sorteaza alfabetic inainte de a le procesa mai departe.Pentru sortare
s-a utilizat metoda implicita.Obiectul contine insa trei astfel de metode
supraincarcate,pentru a permite mai multe variante de abordare (Exemplu:
puteti crea un algoritm propriu pentru sortarea datelor,in functie de
unul sau mai multe criterii specifice.).
Incercati sa scrieti acelasi exercitiu,cu un obiect de tip List.In
aplicatiile noi,este mai bine sa utilizati tipurile generice,deoarece
contin si coduri mai moderne si pot fi adaptate mult mai usor pentru a
crea aplicatii noi,sau pentru a exploata si alte resurse (ce contin
alt tip de date decat cel proiectat initial).
Elementele din lista ArrayList sunt indexate numeric,de la zero pana
la ultimul element din colectie.Pentru a selecta un element oarecare,se
poate utiliza numarul de indexare.Optional se pot face si operatii cu
grupuri de elemente.(Exemplu: de la elementul 10 pana la elementul 23 )
-74-