P. 1
Tutorial C#

Tutorial C#

|Views: 3,400|Likes:
Published by Bablo Bigazzo

More info:

Published by: Bablo Bigazzo on Mar 11, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as DOC, PDF, TXT or read online from Scribd
See more
See less

07/20/2013

pdf

text

original

Namespaces – Spatiile de nume

De ce a fost nevoie de namespaces? Practic, programele mari sunt impartite in module si sunt dezvoltate separat de mai multe persoane. Din acest motiv, exista posibilitatea de a aparea identificatori cu acelasi nume. Solutia la aceasta problema a fost introducerea cuvantului cheie namespace, care, in teorie, se defineste ca o regiune declarativa ce ofera o modalitate de a separa un set de nume de un altul. In concluzie, numele din cadrul unui spatiu nu va intra in conflict cu acelasi nume declarat in alt spatiu.

Declarare namespace. Directiva using Concret, am definita o clasa cu numele Exemplu. Aceasta ar putea intra in conflict cu o alta clasa Exemplu folosita de programul nostru si care este dezvoltata de o alta persona. Folosind spatiile de nume, evitam acest tip de problema. Forma generala pentru declararea unui spatiu de nume este :
namespace Nume { //membri }

Nume reprezinta numele spatiului. Toate entitatile definite in interiorul spatiului fac parte din domeniul de valabilitate al acelui spatiu de nume ( se pot adauga clase, structuri, delegari, enumerari, interfete si surpriza! chiar un alt spatiu de nume ). Intr-un fisier sursa, se pot adauga oricat de multe spatii de nume, iar fiecare spatiu poate contine oricat de multe entitati.

namespace A { public class Exemplu { //proprietate public string Mesaj { get; set; } } }

Clasa Exemplu, care contine o proprietate numita Mesaj, este definita in domeniul de valabilitate al spatiului de nume A. Atunci cand e nevoie de crearea unei instanta a clasei, numele clasei trebuie sa fie calificat cu numele spatiului. Acest mod este cunoscut ca “fully qualified name“.
A.Exemplu ex; ex = new A.Exemplu();

Nu mai este necesar sa calific cu numele spatiului obiectul sau pe oricare din membrii sai. In cazul nostru, proprietatea Mesaj, poate fi apelata direct.
ex.Mesaj;

Normal, situatia va deveni dificila cand programul va include referinte mai multe catre un spatiu de nume si va trebui specificat numele de fiecare data. Solutia vine de la directiva using, care va asigura vizibilitatea spatiului de nume.
using A;

Acum, declararea se poate face asa :
Exemplu ex; ex = new Exemplu();

Compilatorul va cauta in mod automat in spatiul de nume A si in cazul in care va gasi clasa Exemplu, o va folosi. In cazul in care va gasi aceeasi clasa in doua spatii de nume diferite, va trebui specificata clasa si spatiul de nume dorit. Spatii de nume imbricate Este posibil ca un spatiu de nume sa fie imbricat in interiorul altuia.

namespace A { namespace A1 { public class ExempluA1 { // } // } public class ExempluA { // } }

Acest lucru ajuta la divizarea in parti mai mici a codului pentru un mod de lucru mai organizat si mai eficient. Pentru a instantia clasa ExempluA1, trebuie neaparat sa folosesc modul “fully qualified name”.
A.A1.ExempluA1 exA1 = new A.A1.ExempluA1();

Folosirea “fully qualified name” nu pare foarte eficienta in scrierea codului , dar este recomandata pentru usurinta identificarii spatiilor de nume, mai ales in lucru in echipa. Spatii de nume aditive Pot exista mai multe declaratii namespace cu acelasi nume. Acest lucru permite distribuirea unui spatiu de nume in mai multe fisiere sau chiar separarea sa in cadrul aceluiasi fisier.
namespace B { public class Student { // } } namespace B { public class Profesor { // } }

La compilare, continutul ambelor spatii de nume B va fi unit. In cazul in care se redefineste o clasa, apare eroare la compilare.

De exemplu. FileInfo. dar printre cele mai cunoscute sunt: System. etc) si exista Dictionaries (Hashtable. SortedList. Acest spatiu reprezinta radacina pentru toate spatiile de nume din . In acest namespace sunt definiti 3 delegates: ErrorEventHandler. StringDictionary. care este radacina intregii ierarhii de mostenire din Framework. Spatiile de nume reprezinta un concept fundamental in C# si orice program utilizeaza un spatiu de nume intr-un fel sau altul.Spatiile de nume constituie un instrument pentru organizarea programelor si cresterea durabilitatii in mediile distribuite moderne. Important de stiut este faptul ca acest spatiu contine clasa Object.Int16 numar = 0. . De exemplu. BinaryReader. System. el contine si tipurile de date.IO Spatiul Input Output contine clase folosite pentru operatiile de intrare-iesire cu fisiere.Net (implicit. Exista colectii utile pentru cresterea performantei in diferite scenarii (ArrayList. Exista multe alte spatii de nume subordonate lui System. De asemea. Queue. BinaryWriter au functii ce folosesc la accesarea unui fisier de pe disc. care contin alte parti ale bibliotecii limbajului c#. la inceputul oricarui program.Collection Permite dezvoltatorilor sa lucreze usor cu grupurile de obiecte. Acest namespace include si clase folosite in manipularea datelor aflate in memoria aplicatiei: MemoryStream. Ea furnizeaza toate metodele si proprietatile pe care toate obiectele trebuie sa le suporte. Tot in acest namespace sunt definite clase folosite in manipularea fisierelor si directorilor: DirectoryInfo. clasa Object va fi clasa implicita de baza. Stack. clasele File. este inclusa linia de cod: using System. biblioteca limbajului c#) este System. Un exemplu de spatiu de nume folosit pe care il foloseste biblioteca arhitecturii . etc) cu principiul cheie-valoare. StreamWriter. DriveInfo. O lista cu cele mai utilizate spatii de nume nu poate fi stabilita exact. se poate declara si initializa o variabila de tip int. FileSystemEventHandler si RenamedEventHandler. Daca se defineste o clasa fara a se specifica in mod explicit faptul ca aceasta mosteneste o anumita clasa. Astfel.Net. astfel: System.

tranzactii si multe altele.Data Pentru orice operatie cu o sursa de date externa. Daca un limbaj de programare nu furnizeaza un mod pentru stocarea datelor.Window.Text Contine clase care permit codarea si decodarea caracterelor. functii pentru deschiderea / inchiderea conexiunii. Ele stabilesc limitele unui limbaj si determina tipurile de activitati pentru care poate fi utilizat. Nu exista conceptul de variabila fara “tip” pentru ca tipul unei valori determina in mod exact operatiile permise asupra sa (nu toate operatiile sunt permise asupra tuturor tipurilor). System.Text. etc) responsabile cu: date referitoare la sursa de date. System. O variabila este o locatie de memorie cu nume. System. careia ii poate fi stocata o valoare.Web. Acest spatiu de nume contine clase in mai multe subspatii (SqlClient. System. O imagine de ansamblu asupra . O constanta (literal).Diagnostics E un spatiu de nume foarte util in “depanarea” aplicatiei (debug).Services – pentru crearea serviciilor web. Valoare se poate modifica pe parcursul executarii programului.5 si a spatiilor de nume organizate pe tehnologia folosita. Decoder. clasa Process care furnizeaza o functionalitate pentru monitorizarea proceselor sistem din retea. Foarte utilizate sunt si sub-spatiul System. .Web.System. spre deosebire de variabila. Pentru fiecare tip de data. desemneaza o valoare fixa. pe site-ul Microsoft! Tipuri de date Tipurile de date si operatorii stau la baza oricarui limbaj de programare.Forms pentru crearea interfetei utilizator a unei aplicatii Windows. pornirea si oprirea proceselor sistem locale. OleDb. Are clasa EventLog ce permite interactiunea cu event log din Windows.RegularExpressions si clasa StringBuilder.UI – pentru crearea formelor web. trebuie stabilita o conexiune cu acea sursa. Encoder. C# are un mod de declarare. System. Sunt cazuri in care se adauga spatii de nume specifice tipului de proiect. atunci el este inutil. Clasa PerformanceCounter pentru monitorizarea performantei sistemului. Un program opereaza cu date.Net Framework 3.

Comentariile (foarte importante !) intr-un program C# se fac prin folosirea // pentru a comenta un rand.Object. ”value semantics”). In cazul acestor tipuri de date.Text. using System. fiecare cuvant este scris cu majuscula (ex. spatiilor de nume. numit Seat Masina seat = new Masina(). o sa adoptam urmatoarea conventie de scriere. enumerarilor. primul cuvant incepe cu minuscula (variabila anFabricatie).ValueType.Collections. I – tip valoare. metodelor. Cand se face atribuirea. Toate tipurile de date sunt derivate din tipul System. Aceste verificari sunt necesare pentru prevenirea erorilor si cresterea fiabilitatii programelor. In cazul variabilelor. Asta inseamna ca pentru toate operatiile.Generic.De ce tipurile de date sunt importante ? C# este un limbaj puternic tipizat. atunci cand se declara o variabila. interfetelor. iar pe mai multe randuri se folosesc /* */ . compilatorul efectueaza verificari privind compatibilitatea tipurilor. proprietatilor. Tipuri valorice in C# Limbajul C# contine doua tipuri generale de tipuri predefinite. using System. using System. //atribui o valoare variabilei an a instantei seat . are loc o copiere a datelor in variabila destinatie care nu mai este legata de variabila initiala (transmitere prin valoare.variabilele contin valoarea implicita specifica tipului. numita conventia Pascal : in cazul numelor compuse din mai multe cuvinte. Toate tipurile sunt derivate din clasa System. AnFabricatie) – valabila pentru numele claselor. } class Program { static void Main(string[] args) { //creez obiectul masina. va fi nevoie si de alocare de spatiu pentru ea. Initial. namespace ExempluTipuriValoare { public struct Masina { //variabila instanta public int anFabricatie. Pentru urmatoarele exemple.

anFabricatie).anFabricatie). //schimb valoarea variabile an a instantei seat seat.".WriteLine(opel. opel.WriteLine("Masina Seat este din anul {0}.anFabricatie). } } } II – tip referinta.anFabricatie = 2010. seat. Console. seat. // se initializeaza prin copiere variabila sb Console.WriteLine("Masina Opel este din anul {0} prin initializare.Read(). seat.anFabricatie). “reference semantics”).WriteLine("Masina Opel este din anul este {0}. Console. Console.".anFabricatie). Console. Console. Initial. referintele sunt null.seat.WriteLine(seat. Console. //valoare variabilei an a instantei opel ramane aceeasi Console. iar la atribuire este copiata referinta in destinatie.". .anFabricatie = 2009. Masina opel = seat. Masina opel = seat.ReadLine(). In cazul acestor tipuri de date.anFabricatie).".WriteLine("Masina Seat este din anul {0}. E nevoie de alocare explicita de memorie pentru obiectele propriu-zise. opel. Masina seat = new Masina(). la declararea unei variabile nu are loc automat alocarea de spatiu.anFabricatie = 2009. obiectul spre care indica ramanand acelasi (“aliasing”.

Pentru ca C# respecta un domeniu de valori. limbajul asigura portabilitate. int. uint. Pentru a putea detine mai mult control si ordine. . ushort. iar la cele fara semn. Se recomanda ca atunci cand e nevoie de o valoare ( fara semn ) care depaseste domeniul lui int. aritmetica normala cu numere intregi. byte. Variabilele de tip int se utilizeaza in controlul buclelor. ulong. sbyte. Memoria stack are o structura de tip FIFO (first in. Conform MSDN. indexarea tablourilor. o variabila declarata de tip int. long. memoria heap are nevoie de un “memory manager” si un “garbage collector”. Ca avantaj este faptul ca obiectele pot fi alocate si sterse intr-o ordine aleatoare.Sistemul de operare si Common Language Runtime impart memoria folosita pentru stocarea datelor in memorie stiva (stack) si memorie heap.sa se foloseasca uint. toate sunt folosite la calcule numerice. Asta ne ajuta la evitarea rescrierii codului pentru adaptarea programului la o anumita platforma. iar fiecare tip valoric are un comportament. ulong. tipurile valoare se clasifica astfel : I – Tipul structura – care cuprinde : Tipuri numerice Intregi In C# sunt definite 9 tipuri de intregi : char. Ca un exemplu practicStiva retine variabilele de tip valoare. va ramane tot de tip int. Limbajul C# include doua categorii de tipuri de date : tipuri valorice si tipuri referinta. Vom continua cu tipurile valorice fundamentale in C#. De exemplu. Tipurile de date reprezinta un subiect foarte vast. last out) si este foarte eficienta. indiferent de mediul de executie. Heap retine variabilele create dinamic. short. In cazul valorilor mari este recomandat long. fiecare functionand in mod diferit. Cu exceptia lui char.

//un alt mod de a declara un tip double double mediaSemDoi = new double(). //Afisarea rezultatului in consola Console.45. //CALCUL ARIA aria = latime * lungime. este cel mai intrebuintat. . se utilizeaza pentru reprezentarea numerelor care au parte fractionara.Write("Aria este {0} metri patrati. //declarare si initializare int lungime = 40. In virgula mobila Tipurile in virgula mobila. //declararea unui double cu valoare implicita 0 double mediaAn.". //un alt mod de a declara un int int latime = new int(). Acesta din urma.//declararea unui int cu valoare implicita 0 int aria. //atribuire valoare pentru variabila latime latime = 30. double. aria). Exista doua tipuri : float. //declarea si initializare double mediaSemUnu = 8.

1m. Console. Caractere . //un alt mod de a declara o variabila decimal decimal dobanda = new decimal().WriteLine("Noul sold este {0} USD ".WriteLine("a este {0}". sold). Decimal Tipul decimal este folosit in calculele monetare. El are avantajul ca elimina erorile de rotunjire atunci cand se lucreaza cu valori fractionare. Console.WriteLine("b este {0}".//atribuire valoare pentru variabila mediaSemDoi mediaSemDoi = 9. b = true.10m. //afisarea in consola a rezultatului Console. //CALCUL SOLD NOU sold = sold + sold * dobanda. dobanda = 0. Teora bool a. Nu se poate converti.0M decimal sold = 1000. C++. bool b. trebuie urmate de m sau M //declarea unei variabile decimal cu valoare implicita 0. Tipul decimal nu exista in C. //variabile de tip decimal. Java.65.WriteLine("Media anuala este {0}". a = false. Tipuri Bool Tipul bool retine valorile de adevar ( “true” ) si fals ( “false” ).in declarare. pentru ca poate reprezenta in mod precis pana la 28 de pozitii zecimale. mediaAn). //CALCUL MEDIA mediaAn = (mediaSemUnu + mediaSemDoi) / 2. Orice expresie de tipul bool va lua una din aceste valori. //afisarea rezultatului in consola Console. a). b).

constructori. long.In C#. nu vor fi probleme cu administrarea memoriei. operatori. System. ch = 'b'. varsta. proprietati. prenume. //afisarea valorii din standardul UNICODE pentru un caracter //are loc conversia catre un int Console. //declararea unei variabile char cu valoare implicita '\0' char ch.Int32. metode. Atat timp cat structura este rezonabila in ceea ce priveste marimea.Int64.WriteLine("Valoarea lui {0} in standardul UNICODE este {1}". indexatori. va fi stocata in stiva. struct { public public public } III – Tipul enumerare Tipul enumerare se defineste de programator si se aseamana cu cel din C++. campuri. Cele mai simple structuri. pentru tipurile de baza int. sunt System. Acest tip permite folosirea numelor carora li se atribuie o valoare. etc. System.ch. float.Single. Sintaxa pentru a defini o enumerare este : [atribute] [modificatori] enum NumeEnum : [tip] string string int Persoana nume. Este recomandat sa declaram si sa definim o enumerare direct in interiorul unui spatiu de nume. se utilizeaza modelul Unicode. pentru caractere. Pentru ca este un tip valoric.(int)ch). pentru a putea fi folosita de toate clasele. O structura poate contine declaratii de constante. . II Structura – tip valoare propriu Este asemantor cu cel din C++.

Nullable <T>. initializat variabila ‘Luni’ cu 1. in care se doreste ca valoarea implicita a variabilei sa nu fie definita. Tipurile nullable Sunt tipuri valoare pentru care se pot memora valori posibile din aria tipurilor de baza.ZileSaptamana. cu o unitate. in Enum. T este un tip valoare . . "Miercuri"). Sambata. Daca nu foloseam conversia in exemplu ( int ). Marti.Miercuri).ValueType.WriteLine("Miercuri (int)tipulEnum. Valoarea unei variabile contine valoarea implicita a tipului. acesta este considera implicit int. derivata din System. Apoi. Se foloseste structura System.Parse(typeof(ZileSaptamana). astfel : Nullable<int> a . rezultatul ar fi aratat numele elementului. inclusiv valoare null. Pentru a converti un tip string. ( [] – optional ) namespace tipulEnum { enum ZileSaptamana { Luni = 1. Pentru un exemplu simplu si practic. Miercuri.In cazul in care nu se specifica tipul enumerarii. este a {0} zi din saptamana ". se procedeaza in felul urmator: ZileSaptamana zi = (ZileSaptamana) Enum. Tipurile enum sunt derivate din clasa System. Observatii: Implicit. Exista cazuri. valoare primului membru din enumerare este 0. Vineri. fiecare variabila care va urma va avea o valoare implicita mai mare decat precendenta. Duminica } } Un exemplu de folosire a acestei enumerari este : Console. de exemplu avem numele zilei. Joi. daca nu este initializata explicit.Enum.

} care este un ciclu infinit.. i <= 5. while(true) { // . i++) { //executa ceva de 5 ori } O alta modalitate de scriere a unui bloc for este urmatoarea: for (. . for (... Tipuri repetitive In limbajul c# exista mai multe posibilitati de a executa in mod repetat anumite blocuri de cod (ciclu). //intrerupe ciclul .WriteLine(“valoarea variabilei este {0}”. ) { // . Aceste posibilitati sunt: • • • • for while do…while foreach Aceste instructiuni sunt specifice multor limbaje si intelegerea folosiri lor ar trebui sa fie usoara pentru oriceine le-a mai folosit cu alte limbaje. } //intrerupe ciclul O alta modalitate de a scrie un bloc ce se repeta la infinit este cu ajutorul keyword-ului while: int i = 0. . iar verificarea se poate face in felul urmator: Console. a ?? “null”).. Acest bloc de cod ar trebui intrerupt (printr-o intructiune break. Cel mai simplu ciclu este ciclul for.Un alt mod de a declara o variabila de acest tip este: int? a = null. if(i++ == 5) break. Le voi analiza pe rand. Sintaxa generala este: for (int i = 0. ca in exemplul urmator: int i = 0. if(i++ == 5) break.. exemplificand utilizarea lor.. ) { // .

while (x % 5 != 0) { Console. Diferenta dintre un bloc while si un bloc do…while este ca instructiunile din do…while se executa cel putin o data – conditia de iesire din loop se verifica dupa cel putin o executie. 2. insa putin diferit de modurile cum lucreaza blocurile descrise anteorior.WriteLine(x++). De exemplu: int x = int. codul blocului while nu se executa nici macar o data. 4. foreach executa blocul de comenzi asociat o singura data pentru fiecare element dintr-un array sau colectie de obiecte – conditia ca foreach sa poata fi aplicat colectiei este ca acea colectie sa implementeze interfata IEnumerable (sau IEnumerable<T>). } Acest exemplu va afisa perechi de tipul n -> 2n pentru fiecare numar din array-ul de int folosit.NET . Instructiunile do…while sunt o alta metoda de a executa inmod repetat anumite linii de cod: int x = 0. 6.ReadLine()).WriteLine(x). 2 * n). foreach (int n in numbers) { Console. deoarece este o metoda de a executa in mod repetitiv anumite operatii. x++. n. 7. 8.Parse(Console. do { Console. Conversia datelor in . 3. 5. Am lasat la final foreach.} Acest bloc de cod este echivalent (functional) cu cel anterior (folosinf for). } while (x < 5). Exemplu folosind un array: int[] numbers = new int { 1.WriteLine("{1} -> {2}". Codul dintr-un ciclu while poate sa nu fie executat niciodata. } Daca userul introduce un numar multiplu de 5. 10 }. 9.

sa fie tratata ca o expresie de un alt tip. voi introduce un capitol care se leaga strans de tipurile valorice numerice si anume conversiile. Deocamda. Exista doua tipuri de conversii numerice : Conversii implicite . cunoastem structura tipurilor de date astfel : Definim expresie in modul urmator : O expresie este o combinatie valida de operatori. literali si variabile. O conversie permite ca o expresie de un anumit tip.Inainte de a continua prezentarea tipurilor de date din C#.

Eroare la compilare: “Cannot implicitly convert type ‘float’ to ‘int’. //atribuim unui int unui float //valoarea lui i este intai convertita la tipul float //apoi atribuita lui f f = i. f = 30.Conversia implicita se efectueaza automat doar daca nu este afectata valoarea convertita ( tipul destinatie este mai cuprinzator decat tipul sursa ) si cele doua tipuri sunt compatibile. atunci valoarea din partea din dreapta este convertita la tipul din partea stanga. i = 10.4F. invers nu se poate efectua automat. An explicit conversion exists (are you missing a cast?)“ Conversii explicite . int i. float f. float f. Chiar daca se poate efectua conversia automata din int in float. i = 10. Daca sunt indeplinite cele doua conditii. int i. //conversia automata nu are loc i = f. Tipul float este suficient de cuprinzator pentru a memora orice valoare de tip int(conversie prin largire ).

tip – tinta – tipul la care dorim sa convertim expresia expr. Se observa ca partea fractionara se pierde. (tip-tinta) expr. Console. //codul ASCII pentru X b = 88. Console.Pentru a rezolva eroare de mai sus. Console. char ch. Aceasta se realizeaza cu metoda ToString din clasa Object.WriteLine("Valoarea dupa conversia de la float la int este {0} ". f). //cast intre tipuri incompatibile ch = (char)b. byte b. i). f = 30. float f. Una din cele mai intalnite conversii in programare este cea din tipul numeric in sir de caractere. atunci cand valoarea in virgula mobila este convertita la un tip intreg ( conversie prin restrangere ). este nevoie de folosirea unui cast (o directiva catre compilator pentru convertirea unui tip in altul).WriteLine("Valoarea inainte de conversie {0} ".WriteLine("ch : " + ch). . int i. //conversie cu trunchiere i = (int)f.4F.

Console. pe stiva. Valoarea este o copie a valorii asignate variabilei a. //declararea si initializarea unui tip valoare int a = 2009. Daca sirul de caractere nu reprezinta un numar valid. //schimba valoarea a = 2010. Conversiile boxing si unboxing Boxing (“impachetare”) permite ca tipurile valoare sa fie tratate ca obiecte.WriteLine("Valoarea tipului obiect este {0}".s.s. o). a.GetType()). Console.GetType()). care se realizeaza cu metoda Parse din clasa Object. . string s = a. Console. string s = a. apoi copiaza valoare catre instanta.WriteLine("{0} este {1}". s.WriteLine("{0} este {1}". “Impachetarea” unei valori a unui tip valoare se realizeaza prin alocarea unui obiect si copierea valorii in obiectul nou creat.ToString(). a. La fel de folosita este si conversia din caractere in numar. Boxing este o conversie implicita.WriteLine("{0} este {1}".int a = 2009. Rezultatul va fi crearea unui obiect 0. a).care va fi referinta catre o valoare de tip int. a. conversia sirului la numar va esua.GetType()). s. int a = 2009. Console. pe stiva. //boxing asupra variabilei de tip valoare object o = a. O operatie de unboxing consta in verificarea faptului ca obiectul instantiaza o valoare “boxed” a unui tip vlaoare.WriteLine("Valoarea tipului valoric este {0}". Console.WriteLine("{0} este {1}".GetType()).ToString(). “Unboxing” permite o conversie explicita de la tipul obiect la orice alta valoare de tip valoare. Console. a.

O alta conversie pe care vreau sa o mentionez este cea din Enum in int si invers. a). j). O imagine explicativa se gaseste in articolul Tipuri de date in C#. Tipuri de date in limbajul c# – tipuri valorice.Net scrie: Tipurile referinta permit accesul la datele necesare din locuri diferite ale programului. Declararea tipurilor referinta nu implica automat alocarea de spatiu. “reference semantics”). Console.WriteLine("Valoarea noului tip valoric.Luni. dupa unboxing este {0}". Console. //unboxing j = (int)o. iar la atribuire este copiata referinta in destinatie. Structura completa a tipurilor de date : .ZileSaptamana. //luni va fi egal cu 1 sau putem tipulEnum. obiectul spre care indica ramanand acelasi (“aliasing”. Daca avem enumeratia prezentata in exemplul din postarea anterioara. E nevoie de alocare explicita de memorie pentru obiectele propriu-zise. //schimb valoarea pentru tipul valoare a = 2010. Console. Tipurile referinta in . ZileSaptamana putem scrie: int luni = (int)tipulEnum.ZileSaptamana)1.int a = 2009. //boxing object o = a. ca in cazul tipurilor valoare.ZileSaptamana luni = (tipulEnum.WriteLine("Valoarea tipului valoric este {0}". o).WriteLine("Valoarea tipului obiect este {0}". int j = 0.

Pentru a stapani bine C#. //metoda de afisare public void Afiseaza() . public string prenume. Ele definesc natura obiectelor si reprezinta un sablon prin care se defineste forma unui obiect. Intr-o clasa sunt definite datele si codul care prelucreaza acele date.Tipurile referinta se clasifica astfel : Tipul clasa – class Clasa este unitatea de baza pe care este contruit limbajul C#. public string nume. Exemplu : public class Student { public int nota. elementul clasa este esential ( intreaga activitate a unui program C# se desfasoara in interiorul unei clase). Clasele ofera baza pentru programarea orientata pe obiect.

la crearea unui tip delegat se creaza un obiect care poate memora o referinta catre o metoda. Tipul obiect – object Acest tip se bazeaza pe Sytem. nota). Tipul interfata – interface O interfata defineste un set de metode care vor fi implementate de o clasa. Spre deosebire de alte limbaje. Interfata poate fi privita ca un “contract” iar clasa sau structura care o implementeaza.Object din . Student student. Un exemplu concret va fi dezbatut in articolul despre interfete. Console. Tipul delegat – delegate Prin cuvantul cheie delegate se defineste o delegare care nu inseamna decat o referinta catre o metoda. unde tipul string este un tablou de caractere. un mecanism prin care o clasa ( derivata ) preia anumite caracteristici ale unei alte clase ( de baza). nume. student = (Student)a.WriteLine("{0} {1} are nota {2}". O interfata reprezinta o constructie pur abstracta si poate contine metode. prenume. trebuie sa il respecte. Clasa string are o dimensiune relativ mare. evenimente. O interfata poate mosteni mai multe interfete.nota). Asadar. Exista doua tipuri de siruri . Pe langa exemplele din articolul Conversii despre boxing si unboxing unde se prezinta atribuirea valorilor de orice fel variabilelor de tip object.WriteLine(student. indecsi. proprietati. Tipurile clasa suporta mostenirea. metoda care poate fi apelata prin intermediul referintei. Un exemplu concret va fi dezbatut in articolul despre delegate. Tipul sir de caractere – string Tipul string este unul din cele mai importante si utilizate tipuri de date. object a.Net Framework.{ } } Console. in C# tipul string este un obiect. Un exemplu concret va fi dezbatut in articolul despre mostenire. a = new Student(). iar o clasa poate implementa mai multe interfete. El defineste si implementeaza sirurile de caractere. adaug un exemplu in care se atribuie o valoare referinta.

Tipul acesta de sir incepe cu “@” inainte ghilimelor. “verbatim” – se folosesc cand se fac referiri la fisiere. Despre ARRAYS Un tablou reprezinta o colectie de variabile de acelasi tip. Diferenta dintre tablourile din alte limbaje si cele din C#. tablourile sunt implementate ca obiecte.regulate – contine intre ghilimele zero sau mai multe caractere. inclusiv secvente escape (reprezentarea caracterelor care nu au reprezentare grafica si a celor speciale). la registri. string cale = @"c:\TipReferinta\string. fapt care conduce la colectarea automata a spatiului ocupat de tablourile neutilizate. Pentru concatenarea (unirea) sirurilor de caractere se mai foloseste operatorul “+”. . aici. Tablourile se utilizeaza oriunde exista nevoia de a grupa mai multe variabile de acelasi tip la un loc pentru a putea fi gestionate si sortate cu usurinta. tablourile pot avea mai multe dimensiuni. Un exemplu complet in articolul despre clasa System. Pentru comparare se folosesc “==” si “!=” – egalitate inseamna daca ambele sunt null sau daca ambele au aceeasi lungime si pe fiecare pozitie au caractere respectiv identice.Text.Accesul se face printr-o variabila referinta. este ca. In C#. string sir = "Limbajul C# este accesibil!". Exemplu : string sirConcatenat = "Limbajul " + "C#" + " " + "este accesibil".cs". referite prin intermediul unui nume comun. la prelucrarea lor.

Tip [] nume. initializare. 12. initializare int[] colectie = new int[] { 23. //declarea unui tablou unidimensional //nu se aloca spatiu pentru memorie int[] colectie. instantiere. se creeaza o instanta a clasei . apeland metode ale System. La declarea unui tablou. toate tablourile au indexul primului element egal cu zero. 5.Unidimensionale – intalnite foarte frecvent in programare.Array. La declararea unui tablou folosim tipul variabilei. 3. Numarul valorilor dintre acolade trebuie sa fie egal cu numarul care indica marimea vectorului. 6 }. In C#. int[] colectie = { 1. apoi avem nevoie de “[]” si la sfarsit identificatorul. Compilatorul va calcula marimea din numarul de initialzari.Net. Un mod in care se pot face in acelasi timp si operatiile de declarare. este : //declarare. //atribuim primului element o noua valoare colectie[0] = 100. Compilatorul va traduce operatiile asupra tablourilor. //instantiere si alocare de memorie //zona de memorie cu 4 elemente de tip int colectie = new int[4]. instantiere. System.Array. altfel va aparea eroare la compilare.4 }. 23. 4. Un element din tablou poate fi accesat utilizand un index ( descrie pozitia elementului din cadrul tabloului ). Se poate omite declararea marimii vectorului si folosirea operatorului new. .

Sort(listaNume). il vom folosi pentru a creea vectori de tip implicit. Daca se adauga si alte variabile de alt tip. Un exemplu de sortare “custom” poate fi vazut pe programare. Variabila de iteratie nu poate fi modificata in timpul utilizarii ei in accesul la tablou.WriteLine("{0}". este atribuirea pentru fiecare tablou a proprietatii Length. "Andrei" }. tip nume-var specifica tipul si numele unei variabile de iterare. Console. "Florin". interfata care defineste relatie de ordine intre oricare doua elemente de tipul dat.Sort permite sortarea elementelor dintr-un tablou.WriteLine("Sortare alfabetica :\n "). tablourile sunt implementate ca obiecte. Metoda Array.Sort sorteaza doar obiecte care implementeaza IComparable. foreach ( tip nume-var in colectie ) instructiue.0. Un avantaj al faptului ca. } Incepand cu versiunea 3.org: .WriteLine(i). System. In articolul acesta. care va primi la fiecare iteratie valoarea unui element din colectie. C# introduce cuvantul cheie var.Introducem instructiunea foreach. utilizata pentru iterarea elementelor unei colectii. in C#. Exemplu : .Net IComparer. care contine numarul de elemente pe care tabloul le poate memora. va aparea eroare la compilare. Exemplu : //utilizarea foreach pentru afisarea valorilor din vector foreach (int i in colectie) { Console. Trebuie ca tip sa fie compatibil cu tipul de baza al tabloului. nume). } De remarcat ca Array. Exemplu : //compilatorul identifica variabila nume ca un vector de string var listaNume = new[] { "Elena".Array. foreach (string nume in listaNume) { Console. indiferent de tipul acestuia.

23. Cand incercam sa atribuim o valoare de tipul referinta la un tablou al unei altei valori de tip referinta ( copiere ). int[] colectie1 = { 4. foreach (int numar in colectie1) { Console. } Tablourile multidimensionale Tablourile multidimensionale au doua sau mai multe dimensiuni. } //colectie2 refera pe colectie1 colectie2 = colectie1.WriteLine("Elemente colectia1:"). int[] colectie2 = { 23. Cele mai simple tablouri multidimensionale regulate sunt cele bidimensionale. 4.WriteLine(numar). 5. de elemente din vector este {0}". 23 }.2].WriteLine(numar2).WriteLine("Elemente colectia2 :").WriteLine("Dupa atribuire :"). pozitia unui anumit element este data de doi indici.WriteLine("Elemente colectia2 :"). 5 }.Console. 23. } Console. In cadrul acestui tablou.WriteLine("Numarul listaNume. Console. Console. //dimensiune 2X2 int [.WriteLine("Elemente colectia1:"). foreach (int numar2 in colectie2) { Console. . iar un element oarecare poate fi accesat utilizand combinatia a doi sau mai multi indici. foreach (int numar2 in colectie2) { Console. foreach (int numar in colectie1) { Console.] matrice = new int[2. } Console.WriteLine(numar2).Length). se modifica doar obiectul referit de catre acea variabila.WriteLine(numar). Console. Se face distinctie intre tablouri regulate si tablouri neregulate (tablouri de tablouri – jagged arrays ). Nu se produce o copiere a tabloului si nici continutul unui tablou nu se copiaza in celalalt.

Clasificarea operatorilor Operatorii sunt impartiti 3 categorii. Despre operatori Un operator este un simbol care indica o actiune. Operatori binari – actioneaza intre doi operanzi. Operatorii aritmetici In C#. Operatorii alaturi de operanzi formeaza o expresie. Tablourile reprezinta un raspuns la multe intrebari din programare si sunt utilizate cu succes intr-o mare varietate de scopuri pentru modalitatea convenabila de grupare a variabilelor de acelasi tip la un loc. Operandul este valoarea asupra careia se executa operatia. //Scadere Semnificatie Adunare ( si plus unar ) Scadere ( si minus unar ) Inmultire Impartire Impartire Modulo ( rest ) Incrementare Decrementare . exista urmatorii operatori aritmetici : Operator + * / % ++ – Exemplu : int numar = 5. Operatori ternari – actioneaza asupra a trei operanzi. Operatori unari – actioneaza asupra unui singur operand.//atribuim valoare elementului de pe linia 2 si coloana 1 matrice[1.0] = 230. operatorul conditional. //Adunare Console.WriteLine(numar + numar2). int numar2 = 13. Exista doar unul de acest tip.

//Inmultire Console.Console. restul nu este trunchiat Console.WriteLine(numar2). Console.WriteLine(++numar). Deoarece acesti operatori produc rezultate de tip adevarat sau fals.WriteLine(numar2++).WriteLine("INCREMENTARE PREFIXATA"). //sau folosind expresia x = x-1 numar2 = numar2 .WriteLine(numar2). Console.WriteLine("5"+"5").WriteLine((double)numar2 / numar). Console. Console. //Impartire modulo //returneaza restul impartirii Console. sunt folositi des cu operatorii logici. Exemplu incrementare : //incrementare.WriteLine(--numar). Console.WriteLine(numar * numar2).WriteLine(numar2 / numar). Console. Console.WriteLine(numar++).WriteLine("DECREMENTARE POSTFIXATA").1. Console. cresterea cu o unitate a valorii Console. scaderea cu o unitate a valorii Console.WriteLine(numar2 % numar). Exemplu decrementare //decrementare. //Impartire //restul este trunchiat Console. //sau folosind expresia x = x+1 numar2 = numar2 + 1.numar2). //operatia se va efectua inainte de a calcula valoarea operandului Console. Operatorul "+" este folosit la concateanarea stringurilor : Console.WriteLine("INCREMENTARE POSTFIXATA").WriteLine("DECREMENTARE PREFIXATA"). //conversie la tipul double. Operator == != Semnificatie egal cu diferit de .WriteLine(numar2--).WriteLine(numar . Console.WriteLine(numar--). Operatorii relationali Operatorii relationali se refera la relatiile de ordine care pot exista intre doua valori.

Operatorii logici Pentru operatorii logici. operanzii trebuie sa fie de tipul bool. Console. Console. rezultatul fiind tot de acest tip.WriteLine(true && false). object b = 1.WriteLine(a == b).WriteLine(false && false).WriteLine(true || false). indiferent de valoarea celui de-al doilea operand. Console. rezultatul va fi false. Intr-o expresie logica ce are in componenta operatorul ||.WriteLine(false && true).WriteLine(true && true). indiferent de valoarea celui de-al doilea operand. iar expresia nu va mai fi evaluata. int numar1 = 1.WriteLine(numar1 != numar2). daca primul operand are valoare false. Console. Console. . Exemplu: //Operatorul && Console. rezultatul va fi true. iar expresia nu va mai fi evaluata. int numar2 = 1. Operator ! && || Semnificatie negatie logica SI logic SAU logic Intr-o expresie logica ce are in componenta operatorul &&. daca primul operator are valoare true. Exemplu //Operatorul || Console.< > <= >= Exemplu mai mic mai mare mai mic sau egal mai mare sau egal //obiecte diferite object a = 1.

WriteLine(false || true). atunci va fi returnata valoarea lui expresie2. Desi ajuta la sporirea expresivitatii codului. int y = 10. Operatorul de atribuire Operatorul de atribuire “=” se foloseste intr-o constructie de forma variabila = expresie. Pentru atribuire se mai folosesc si operatorii +=.WriteLine(false || false). Lista poate fi consultata aici. Dupa evaluarea expresiei. supraincarcarea operatorilor poate duce si la crearea confuziilor. rezultatul va fi atribuit variabilei. int z = 67. Daca expresie1 este adevarata. Daca expresie1 este falsa. Prin supraincarea unui operator.WriteLine(true || true). Console. operatiile se executa conform prioritatii operatorilor. *=. se extinde aria de utilizare a acestuia la clasa creata. /=.WriteLine(x < y ? y : z). –=.Console. //6<10 este true. //echivalent Console. Supraincarcarea operatorilor este strans legata de supraincarcarea metodelor. Despre polimorfism . Exemplu : int x = 6. atunci va fi returnata valoarea lui expresie3. Operatorul conditional Este de forma : expresie1? expresie2: expresie3 .WriteLine(a += 5). returneaza valoarea lui y Console. Console. In C# sunt foarte multi operatori iar in cazul in care o expresie nu are paranteze. %=. Efectele operatorului pot diferi de la o clasa la alta.WriteLine(a = a + 5). Supraincarcarea operatorilor Prin supraincarea operatorilor se redefineste semnificatia unui operator in contextul dat de o anumita clasa creata. Console. Exemplu : int a = 5.

de regula se stie numarul parametrilor care vor fi transmisi. sa aiba comportamente diferite. Polimorfismul parametric O metoda va prelua orice numar de parametri. Cu ajutorul acesteia. Sunt cazuri in care nu se intampla acest lucru si va fi nevoie de un numar arbitrar de parametri. Un obiect polimorfic este capabil sa ia mai multe forme. afiseaza un mesaj if (numere. } Polimorfismul ad-hoc Se mai numeste si supraincarcarea metodelor. //in cazul in care nu e transmis functiei //nici un parametru. Acesta va declara un tablou de parametri. //comparam fiecare element al tabloului //cu valoarea minima initiala foreach (int i in numere) if (i < minim) //atribuim valoarea minima variabilei minim minim = i. Cand cream o metoda.WriteLine("Nu sunt parametri"). care poate memora zero sau mai multe elemente. Exemplu : //metoda va returna numarul minim public int metoda(params int[] numere) { int minim. una dintre cele mai interesante facilitati oferite de limbaju C#. Se va recurge la un tip special de parametru. //inapoi la programul apelant al functiei return minim. toate avand . } //initializam variabila //cu primul element al tabloului minim = numere[0].Length == 0) { Console. de tipul params. return 0. sa se afle in diferite stari. mai multe metode” – sintagma pe care se bazeaza conceptul de polimorfism. se pot defini in cadrul unei clase mai multe metode. Se incearca stabilirea unei interfete generice pentru un intreg grup de activitati asemanatoare.“O singura interfata.

sup. Nu este suficient insa. se va apela functia dupa numarul parametrilor folositi la apel.CalculeazaMedia(23. . ca diferenta dintre doua metode sa fie facuta doar prin tipul valorii returnate. dar cu tipul si numarul parametrilor diferit. sup. int nota2) { Console. } //eroare.CalculeazaMedia(10). La compilare.CalculeazaMedia(34. sup. ci e nevoie si de tipurile sau numarul parametrilor.WriteLine("Nici un parametru"). pur si simplu trebuie doar declararea unor versiuni diferite ale sale. } //supraincarcam cu un parametru intreg public void CalculeazaMedia(int nota) { Console. Pentru a supraincarca o metoda. } //supraincarcam cu parametri double public void CalculeazaMedia(double nota) { Console. dar care sunt in clase diferite.acelasi nume. Polimorfismul de mostenire Intr-o ierarhie de clase.34). } //supraincarcam cu doi parametri intregi public void CalculeazaMedia(int nota1.CalculeazaMedia(). Exemplu: class SupraincarcareMetoda { public void CalculeazaMedia() { Console. 23).WriteLine("Doi parametri: " + nota1 + " " + nota2).WriteLine("Un parametru double:" + nota). sup. se pune problema apelarii metodelor care au aceeasi lista de parametri. daca incerc sa suprascriu //doar prin tipul de date returnat public int CalculeazaMedia(double nota) { // } } In metoda principala a programului : //apelam toate versiunile lui CalculeazaMedia SupraincarcareMetoda sup = new SupraincarcareMetoda().WriteLine("O nota:" + nota).

metodele nu sunt virtuale. Implementarea unui membru virtual poate fi schimbata prin suprascrierea membrului intr-o clasa derivata. Nu se pot suprascrie metodele care nu sunt virtuale. Acestea se vor numi membri virtuali. Exemplu: class Baza { public virtual void Afiseaza() { Console.Exemplu: class Baza { public void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n"). obiect2. Override se foloseste pentru a modifica o metoda sau o proprietate si furnizeaza o noua implementare a unui membru mostenit dintr-o clasa de baza. Implicit. Metoda de baza suprascrisa si metoda de suprascriere trebuie sa aiba aceeasi signatura ( tip si numar de parametri ). } } La compilare se rezolva problema apelarii metode Afiseaza. pe baza tipului declarat al obiectelor : Derivata obiect2 = new Derivata().Afiseaza(). Modificatorii virtual si override Virtual este folosit in declararea unei metode sau a unei proprietati. //afiseaza functia din clasa de Baza obiect1.WriteLine("Apelul functiei Afiseaza din clasa de baza\n").Afiseaza().WriteLine("Apelul functiei Afiseaza din clasa derivata"). } } . } } class Derivata : Baza { public void Afiseaza() { Console. //instantiem pe un obiect din clasa derivata Baza obiect1 = obiect2.

prelucrarii si distrugerii datelor. Forma unui obiect este definata de clasa. //instantiem pe un obiect din clasa derivata Baza obiect1 = obiect2. Cand sunt private. codul si datele pot fi private sau public. celelalte parti ale programului le pot utiliza. programarea procedurala si programarea modulara. } } Derivata obiect2 = new Derivata(). cu valabilitate in corpul functiei. Programare orientata pe obiecte Programarea orientata pe obiecte este notiunea de baza a limbajului C# si reprezinta o metodologie puternica de abordare a programarii.Afiseaza().WriteLine("Apelul functiei Afiseaza din clasa derivata"). Incapsularea e un mecanism care combina codul si datele mentinandu-le integritatea in timpul utilizarii. ele sunt vizibile si accesibile doar in interiorul obiectului. Datele care constituie o clasa sunt denumite variabile membri. In cazul public. Programele orientate spre obiect sunt organizate in jurul datelor (ceea ce este afectat de executia programului).class Derivata : Baza { public override void Afiseaza() { Console. polimorfism. Programele contin datele cat si metodele asociate crearii. de tip obiect sau tipul void (nimic). vom discuta in urmatoarele doua articole. //afiseaza functia din clasa de Baza obiect1. poate admite parametri si returna valori de tip predefinit. mostenirea.Afiseaza(). Despre ultimele doua notiuni. Din aceasta combinatie. Exemplu : . In cadrul unui obiect. pornind de la programarea nestructurata. Polimorfismul ajuta la reducerea complexitatii pentru ca permite unei interfete sa fie folosita de fiecare data pentru specificarea unei clase generice de actiuni. Programatorul nu va efectua manual selectia. se creeaza obiectul. Selectia actiunii specifice (metoda) va fi facuta de compilator. Tot la nivelul incapsularii se defineste nivelul de acces la datele unui obiect. Codul care opereaza asupra datelor este numit metoda . Un parametru sau argument este o valoare transmisa unei metode. Metoda implementeaza o actiune. Caracteristicile comune limbajelor care implementeaza programarea pe obiecte sunt: incapsularea. obiect2.

acces permis doar pentru clasa care contine membrul accesibil oricarui membru al al clasei care il contine si al private protected internal .Doar pentru clasele interioare folosit pentru clasele interioare semnificand accesul in clasa care-l contine sau in tipurile derivate din clasa care-l contine Atat datele cat si metodele pot avea modificatori de acces: modificator access public internal protected explicatie membrul accesibil de oriunde accesbil doar intr-un bloc functional al unei aplicatii . In cazul in care nu adaugam un modificator in declarea clasei. clasa Student va fi vizibila peste tot si cu acces nelimitat. private int varsta. ea ar primit implicit tot acest modificator de acces.Net accesibil oricarui membru al clasei care-l contine si al claselor derivate implicit. //declarea unei metode //care va returna true/false public bool Admis() { // } } Datorita modificatorului de acces public. modificator access public internal protected private protected internal Explicatii access nelimitat acces permis doar in clasa sau spatiul de nume in care e cuprinsa acces in clasa curenta sau in cele derivate implicit.public class Student { //declararea variabilelor membru public double nota.

2. precum si in blocul functional Definitia unei clase creeaza un nou tip de data (clasa este un tip de date referinta). Constructorul contine instructiuni care se executa la crearea unui nou obiect al clasei. //constructor implicit public Student() { nota = 0. se va crea un obiect care contine o copie proprie a fiecarei variabile membru din cadrul clasei. La instantierea clasei. this.” . Dupa executia instructiunii. varsta = 0.claselor derivate. se va utiliza operatorul “. } O clasa poate avea mai multi constructori.nota. int varsta) { this.nota). apelam constructorul parametrizat: Student Ionescu = new Student(8. 23). //creeaza un obiect Student Student Popescu = new Student(). Console. Continuand cu exemplu. Daca o clasa nu are definit un constructor.WriteLine(Ionescu. Constructorul Constructorul este o metoda care face parte dintr-o clasa. } //constructor cu doi parametri public Student(double nota. Pentru a referi este variabile. vom creea un obiect de tipul Student. La crearea unei instante.nota = nota.varsta = varsta. . Exemplu: //operatorul punct leaga //numele unui obiect de numele //unui membru al sau Popescu. Popescu va fi o instanta a clasei Student. atunci se va atribui automat constructorul fara parametri al clasei de baza.

Pentru o aplicare cat mai buna a principiilor POO. clasa de baza. toate clasele din C# mostenesc clasa Object. O clasa derivata va mosteni toate variabilele. in mod normal. a datelor si operatiilor. clasa de baza va fi mostenita de alte clase. O clasa derivata este o versiune specializata a unei clase de baza. clase derivate. o proprietate. pentru ca. Prin intermediul lui this. O clasa de baza impreuna cu toate clasele derivate.). Destructorul nu este apelat in mod explicit. Operatorul new Operatorul new este folosit pentru crearea obiectelor si invocarea constructorilor (reamintim ca si la tipurile de date se apela constructorul implicit: int variabila = new int (). se va putea referi la acea variabila membru. Operatorul this Acest operator se refera la instanta curenta pentru care a fost apelata o metoda. proprietatile si indexarile definite in clasa de baza. Operatorul mai este folosit in situatia cand numele unui parametru sau al unei variabile locale coincide cu numele unei variabile membru. numai caracteristici care le identifica in mod unic. la procesul de distrugere este invocat Garbage Collector . In programare. la o relatie intre clase. numele local “va ascunde” variabila membru. In C#. formeaza o ierarhie de clase. unice. o clasa derivata poate mosteni de la o singura clasa de baza ( mostenire simpla ). Apoi. Exemplu de mostenire : . metodele. Cum functioneaza? Definim o clasa generala. Reamintim. ce are caracteristici comune pentru o multime de elemente asemanatoare. a relatiilor dintre entitati si o posibila ierarhie a claselor. Mostenirea este unul din principiile fundamentale ale programarii.Destructorul Corpul destructorului este format din instructiuni care se executa la distrugerea unui obiect al clasei. direct sau indirect. Este nevoie de conceptul de mostenire pentru a evita repetitia definirii unor clase care au in comun mai multe caracteristici. mostenirea se refera la clasificare. O clasa derivata poate fi clasa de baza pentru alta clasa derivata. In acest caz. la declararea constructorului cu parametri). O clasa de baza poate fi derivata in mai multe clase derivate. la care va adauga elemente proprii. (exemplu mai sus. care isi vor adauga pe langa caracteristicile mostenite. sunt importante operatiile de identificare a entitatilor. Operatorul new nu poate fi supraincarcat.

Membrii privati sunt accesibili doar pentru codul din interiorul clasei lor. clasa Dreptunghi nu i-ar mai fi putut accesa. public void AfiseazaDimensiune() { Console.latime = 2.Aria()). Forma forma = new Forma().WriteLine("Aria: {0}". apare cand clasele de baza si clasele derivate dispun de constructori proprii : Ce constructor se utilizeaza pentru a construi un obiect apartinand unei clase derivate? Raspuns : constructorul clasei de baza construieste portiunea . Pentru a putea depasi aceasta problema si a nu fi nevoie sa declaram membri public ( vor fi accesibili in tot restul codului ). deci. In ceea ce priveste sintaxa la mostenire. } } //clasa Dreptunghi mosteneste //clasa Forma class Dreptunghi : Forma { public double Aria() { //clasa Dreptunghi poate //referi membrii clasei Forma //ca membri proprii return inaltime * latime.WriteLine("inaltime: {0}. d1. private double latime. Clasa de baza Forma poate fi utilizata independent. } } In metoda Main : Dreptunghi d1 = new Dreptunghi().AfiseazaDimensiune().latime). dar privati in afara ei. latime: {1}".//clasa de baza class Forma { public double inaltime. Acest modificator de acces face ca membri protejati sa fie public in cadrul unei ierarhii de clase. se observa ca numele clasei de baza urmeaza dupa numele clasei derivate. Console. public double latime. forma. separate de “:”. ). mostenirea NU va anula restrictiile impuse. d1. O intrebare interesanta cand se discuta despre mostenire. Despre accesul la membri : in cazul in care in clasa de baza.inaltime. d1. ( private double inaltime. chiar daca din ea deriva alte clase. una din solutii ar fi declararea membrilor ca protected.inaltime = 32. declaram membri de tip private.

} In acest caz. la compilare va aparea mesajul : . } } Constructorul clasei Dreptunghi initializeaza si membrii mosteniti de la clasa Forma impreuna cu campul propriu stil. } class B : A { int a. //utilizam base pentru //a executa constructorul //clasei de vaza public Dreptunghi(string s. } } //clasa Dreptunghi mosteneste //clasa Forma class Dreptunghi : Forma { //membru variabila privat string stil. //constructor pentru clasa Forma public Forma(double inaltime. _latime = latime. double inaltime. protected double _latime. latime) { stil = s. class A { public int a. double latime) { _inaltime = inaltime. double latime) : base(inaltime.obiectului care apartine de clasa de baza. O alta situatie legata de mostenire este atunci cand intr-o clasa derivata definim un membru al carui nume coincide cu numele unui membru din clasa de baza. constructorul clasei de baza construieste portiunea care apare de clasa derivata. //clasa de baza class Forma { //membri variabila protected double _inaltime.

care se aseamana cu clasele abstract – definesc un obiect fara a specifica implementarea concreta. //aceasta clasa //nu va putea fi mostenita sealed class M { } Modificatorii sealed si abstract nu pot fi folositi impreuna pentru o clasa. //aceasta declarare a lui a //il ascunde pe a din clasa A new int a.a’ hides inherited member ‘Inheritance. se foloseste new. //descopera a //din clasa A base. Este valabil si pentru metode. o clasa nu poate deriva din doua clase. fiecare completand detaliile caracteristice. nu poate fi instantiata. Modificatorul abstract poate fi aplicat si asupra metodelor. . //aceasta clasa //nu va putea fi mostenita abstract class M { public abstract void Metoda(). iar o clasa derivata dintr-o clasa abstract trebuie sa o implementeze in totalitate.a’. Modificatorul abstract In unele cazuri. } Modificatorul sealed Se foloseste in situatiile in care se doreste impiedicarea mostenirii. poate contine metode abstract. Daca se doreste ca membrul clasei de baza sa nu fie vizibil in clasa derivata.‘Inheritance. Chiar daca variabila membru i din B ascunde i din A. in loc de folosirea claselor abstracte se pot folosi interfete.Net nu permite derivarea multipla. este necesar crearea unei clase de baza care stabileste un sablon general comun pentru toate clasele derivate. O clasa pote implementa mai mult de o interfata. folosind base se permite accesul la variabila definita in clasa de baza. O clasa care este definita cu abstract.B.A.a. Pentru ca . proprietatilor. Use the new keyword if hiding was intended.

Atentie. indexatori care vor fi implementate de o clasa. sunt public in mod implicit. Alaturi de polimorfism si incapsulare. interface tip tip } tip – tipul de date returnat de metoda. Dar. lista de parametri – numarul si tipul lor. prin specificarea numelui interfetei dupa numele clasei. cea a interfetelor. proprietati. Toti membri declarati in interfata. nume-metoda(param). Sintactic. Se foloseste cuvantul cheie interface. Dupa definirea interfetei. are o putere mult mai mare. cu mentiunea ca nici o metoda nu poate avea corp. param – signatura metodei. dar NU si CUM trebuie facut. Vezi si articolul despre interfete Interfete Scriam in articolul despre mostenire (inheritance) ca mostenirea unei clase foarte importanta in C#. un altfel de mostenire. public interface Interfata { void Metoda1(). evenimente. Interfata precizeaza CE trebuie facut. interfetele NU implementeaza. ele sunt abstracte si doar isi descriu membrii. } nume nume-metoda { (param). O interfata defineste un set de metode. Exemplu : selectam in Visual Studio numele interfetei si la click dreapta vom implementa interfata : . interfetele sunt asematoare cu clasele abstract.Mostenirea este un concept cheie in programarea orientata pe obiect. void Metoda2(). separate de “:”. o clasa o va putea implementa folosind aceeasi sintaxa ca la mostenirea unei clase de baza.

Exemplu: public interface I1 { void Metoda1(). care sunt de tip public. } #endregion } La crearea unei interfete. O clasa poate implementa un numar infinit de interfete. constante. va trebui sa implementeze toate metodele acesteia. Specificatorii de acces nu sunt permisi. } class A : I1. un destructor.Codul.WriteLine("Metoda2"). void Metoda2().WriteLine("Metoda1"). ca restrictii avem faptul ca nu putem defini un constructor. I2 { . Mai mult. O interfata poate fi implementata de un numar infinit de clase. avand continutul metodelor modificat : //clasa A implementeaza interfata Interfata class A : Interfata { #region Interfata Members public void Metoda1() { Console. } public void Metoda2() { Console. Cand o clasa implementeaza o interfata. void Metoda4(). o interfata nu poate mosteni o clasa sau o structura. O clasa nu poate alege pentru implementare doar anumite metode. } public interface I2 { void Metoda3().

Mostenirea interfetelor O interfata poate mosteni o alta interfata.”. void Metoda2(). } //clasa Test va trebui sa implementeze toate mteodele din A si B . Este intalnita situatia cand o clasa va mosteni o clasa de baza si va implementa una sau mai multe interfete – numele clasei de baza trebuie sa fie primul in lista separata prin virgule. numele acestora vor fi separate prin “. } //interfata B va include metoda1 si metoda2 plus metoda3 public interface B : A { void Metoda3(). Daca o clasa mostenteste o interfata care mosteneste o alta interfata. } #endregion } In cazul in care o clasa implementeaza mai multe interfete. Exemplu : //interfata accesibila in tot programul public interface A { void Metoda1(). } public void Metoda4() { throw new NotImplementedException(). } #endregion #region I2 Members public void Metoda3() { throw new NotImplementedException().#region I1 Members public void Metoda1() { throw new NotImplementedException(). Sintaxa este comuna cu cea folosita la mostenirea claselelor. } public void Metoda2() { throw new NotImplementedException(). clasa va trebui sa contina implementari pentru toti membri definiti pe lantul de mostenire al interfetei.

selectam in Visual Studio numele interfetei si la click dreapta vom implementa interfata in mod explicit . } public void Metoda2() { Console. (la fel ca la mostenirea claselor). prefixand numele membrului cu numele interfetei.class Test : B { #region B Members public void Metoda3() { Console.WriteLine("Metoda2"). Un alt motiv pentru implementarea explicita ar fi ca metoda respectiva nu va fi vizibila pentru codul din afara clasei.WriteLine("Metoda1"). } } #endregion Si in cadrul mostenirii interfetelor. Situatia va genera un mesaj de atentionare si va fi rezolvata prin folosirea operatorului new. poate aparea situatia cand un membru al interfetei derivate are aceeasi signatura cu membrul cu acelasi nume din interfata de baza. Exemplu : Pastram interfetele definite mai sus. Acum.WriteLine("Metoda3"). O implementare explicita este necesara pentru eliminarea ambiguitatii in cazul a doua interfete cu metode care au acelasi nume si aceasi signatura. O implementare explicita inseamna specificarea numelui complet. daca se doreste ca membrul din interfata de baza sa fie ascuns. } #endregion #region A Members public void Metoda1() { Console.

printre cele mai folosite interfete se numara IDisposable. IConvertible (pentru convertirea la tipuri de baza). } #endregion } //metodele implementate explicit.Implementare explicita"). . Chiar daca nu este un obiect. class Test : B { #region B Members void B.Doar la implementarea metodei2 vom aduce modificari. Solutia simpla consta in conectarea butonului la un delegat si apoi acesta sa indice catre o anumita metoda. (folosita pentru eliberarea spatiului de memorie).Metoda1() { Console. iar aici.WriteLine("Metoda3. } #endregion #region A Members void A. lucrul cu interfetele trebuie stapanit foarte bine. O interfata este o constructie pur abstracta. exista situatii cand trebuie sa executam o anumita actiune. la aceasta adresa.WriteLine("Metoda1. etc. dar fara sa stim in avans ce metoda sau ce obiect vom apela pentru executarea actiunii.Metoda3() { Console.Metoda2(). pentru a fi vizibila in afara clasei. Un delegat este un obiect care poate referi o metoda. Pentru un programator. Exemplu : la apasare. o metoda ocupa un loc in memorie.Net. In . IComparable (folosita pentru sortare).Implementare explicita"). nu doar in C#. dar nu stie exact care. un buton va sti ca trebuie sa notifice un anumit obiect . nu vor fi vizibile Test t = new Test(). } //am adaugat public si am sters implementarea explicita public void Metoda2() { Console. Despre delegates In programare. va fi transmis controlul la invocarea metodei. t.WriteLine("Metoda2").

i >= 0. int i. } //returneaza sirul inversat public string StringReverse(string str) { string temp = "".1."). delegate string StringReverseDelegate(string str). Dupa ce a fost declarat. ii putem aplica modificatorii de acces public. class DelegateTest { //returneaza numarul de caractere al unui sir de caractere public int StringLength(string str) { Console. Un delegat se declara cu ajutorul cuvantului delegate. Un delegat este un tip referinta si este este echivalentul unui pointer la functie din C++. private. delegate tip-rez nume (lista-parametri).WriteLine("Va returna numarul de caractere"). i--) temp += str[i]. Intr-o clasa.WriteLine("Inverseaza sirul. Exemplu : //declararea unui delegat delegate int StringLengthDelegate(string str). tip-rez – tipul valorii intoarse de metodele pe care delegatul le va apela. In functie de cum se vrea vizibilitatea lui.Length . } } .etc. construim functiile care vor fi apelate prin delegate. sau in interior. lista-parametri – lista de parametri necesari metodelor care vor fi apelate prin intermediul delegatului. Poate fi declarat in afara unei clase. un delegat poate apela doar metode cu acelasi tip returnat si aceeasi lista de parametri. Console. //parcurgem sirul invers si concatenam for (i = str. return temp.Length.Un delegat reprezinta modul prin care se realizeaza comunicarea intre obiecte. protected. Diferenta este ca delegates sunt type-safe si ca sunt orientati pe obiect. nume –numele delegatului. return str.

//sirul care va fi transmis functiilor string str.StringReverse). MulticastDelegat StringReverse = new MulticastDelegat(test. iar pentru crearea lor se folosesc operatorii += si –=. dupa instantierea unui delegat. Console.ToString() .StringLength). = new //construim delegat Pe scurt: avem doua metode statice in clasa DelegateTest ale caror signaturi coincid cu signaturile delegatilor. Delegarile multicast trebuie sa returneze un rezultat de tip void. //construim delegat StringReverseDelegate strReverse StringReverseDelegate(test.WriteLine(str). Multicasting Multicasting-ul se defineste ca o facilitate a delegatilor si consta in capacitatea de a crea un lant de metode care vor fi automat apelate la invocarea unui delegat. In Main. //apelul unei metode prin intermediul delegarii convertim de la numar la string //pentru ca functia returneaza int str = strLength("Test"). multiDel = StringLength. MulticastDelegate StringLength = new MulticastDelegat(test. //apelul unei metode prin intermediul delegarii str = strReverse("Test"). nu la compilare. construim referinte de tipul StringLengthDelegate si StringReverseDelegate.Determinarea metodei apelate se rezolva la momentul executiei.In metoda Main : DelegateTest test = new DelegateTest(). lucrul cu delegate este intalnit in arhitecturile care permit adaugarea componentelor pe parcurs.WriteLine(str). nu se cunosc metodele care urmeaza a fi executate. StringLengthDelegate strLength = new StringLengthDelegate(test. Se mai observa ca invocarea delegatilor determina apelul metodelor. Console.StringReverse). //construim delegatii MulticastDelegat multiDel. Exemplu : //declararea unui delegat multicast delegate void MulticastDelegat(string str). .StringLength). Datorita faptului ca la compilare. pe care le atribuim metodelor. //crearea unui delegat multicast multiDel += StringReverse.

In articolul urmator, se va observa una din utilitatile delegatilor, anume implementarea evenimentelor.
Despre evenimente

In stransa legatura cu facilitatea delegate a limbajului C#, prezentam evenimentele, events. Cele mai multe evenimente sunt actiuni ale utilizatorilor (click, schimbarea unei liste, introducere de text, sfarsitul unui calcul etc). In .Net, obiectele cunoscute ca si event senders, declanseaza evenimente atunci cand au loc actiuni. Event receivers se ocupa de aceste evenimente prin rularea unei metode numite event handler. Pentru ca event sender-ul nu stie care metoda se va ocupa de eveniment, trebuie creat un delegate care sa se comporte ca un pointer catre event handler. Pentru a produce un eveniment, trebuie sa parcurgem 3 pasi : sa declaram un delegate, sa construim un obiect eveniment, sa apelam delegatul intr-o metoda. Pentru a raspunde la un eveniment, e nevoie de doi pasi: trebuie sa construim o metoda, metoda care trebuie sa se potriveasca signaturii delegatului. Doi, e nevoie sa adauga un event handler care sa indice care metoda trebuie sa primeasca evenimentele. Declararea unui eveniment se face prin folosirea cuvantului cheie event. event delegat-eveniment nume-obiect; delegat-eveniment – numele delegatului folosit pentru tratarea evenimentului; nume-obiect – numele instantei eveniment; Exemplu:
//declaram un delegate //pentru tratarea evenimentului delegate void DelegatTratareEveniment();

Deoarece evenimentele au delegati multicast, tipul rezultatului va fi void. Pentru acest exemplu, nu exista parametri, dar evenimentele pot accepta parametri. Construim o clasa in care definim o instanta eveniment.
class Eveniment { //declaram evenimentul public event DelegatTratareEveniment activat; //metoda apelata la lansarea evenimentului public void Actiune() {

} }

if (activat != null) //lansam evenimentul activat();

Metoda Actiune va fi apelata de program pentru a semnala un eveniment si apeleaza rutina de tratare a evenimentului prin intermediul delegatului activat, daca si numai daca acesta nu este null (verificam faptul ca delegatul nu este null pentru ca este posibil ca metoda Actiune sa fie apelata inainte de inregistrarea rutinei de tratare). In clasa Program a proiectului, construim rutina de tratare numita handler, care in acest exemplu simplu doar va afisa un mesaj.
//rutina de tratare static void handler() { Console.WriteLine("Eveniment produs"); }

In metoda Main, construim o instanta a clasei Eveniment, iar metoda handler este inregistrata ca rutina de tratare a evenimentului.
//crearea instantei eveniment Eveniment ev = new Eveniment(); //adaugam handler-ul la lista de evenimente ev.activat += new DelegatTratareEveniment(handler);

Lansam evenimentul:
//lansam evenimentul ev.Actiune();

Apelul metodei determina apelul rutine de tratare. Multicast Multicast in conceptul evenimentelor permite mai multor obiecte sa raspunda la instiintarea aparitiei unui eveniment. Exemplu: Scriem acelasi cod pentru declararea unui delegat si pentru declararea clasei Eveniment. Adaugam inca doua clase, a caror rutine de tratare nu sunt statice, deci va trebuie sa creeam instante pentru clasele respective.
class A { public void AHandler()

{ } }

Console.WriteLine("Eveniment primit de un obiect A");

class B { public void BHandler() { Console.WriteLine("Eveniment primit de un obiect B"); } }

In clasa Program, adaugam doar in metoda Main:
//crearea instantelor A a = new A(); B b = new B(); //adaugam rutinele de tratare la lisa de evenimente ev.activat +=new DelegatTratareEveniment(a.AHandler); ev.activat += new DelegatTratareEveniment(b.BHandler); //lansam evenimentul ev.Actiune(); //eliminarea unei rutine de tratare ev.activat -= new DelegatTratareEveniment(a.AHandler);

Ca observatie valabila pentru evenimente in acest exemplu : evenimentele sunt destinate instantelor si nu claselor in general. In .Net, mai toate evenimentele sunt implementate folosind delegati multicast, care au doi parametri (unul de tip object – care reprezinta obiectul care provoaca evenimentul, iar celelalt de tip EventArgs care contine data utilizabile in tratarea evenimentului). Putem construi evenimente in interiorul claselor, iar la declansarea lor ne putem da seama unde s-a ajuns cu procesarea codului. Suportul pentru delegate si evenimente permite gestionarea complexitatii programarii pe obiecte intr-un mod mai usor. Exemplul prezentat in acestarticol poate fi downloadat aici.
Despre threads

De multe ori, aplicatiile au nevoie de mult timp pentru a rezolva o sarcina (descarcarea unui fisier, printare, generarea unui raport etc), timp in care programul nu poate raspunde unei alte actiuni a utilizatorului. Pentru a face ca o aplicatie sa indeplineasca o sarcina si sa poata primi si altele in acelasi timp, sunt folosite firele de executie multiple (multiple threads).

Folosirea firelor de executie este o solutie la imbunatatirea performantei. procesul poate reveni ulterior în starea gata de executare pe o baza similara. în urma apelarii procedurii predefinite sleep. limitand performanta. Un thread este o unitate de executie intr-un proces. Daca un calculator are mai multe procesoare sau un procesor cu mai multe nuclee.blocat: inseamna întreruperea executarii procesului pe baza unei relatii (comunicari) cu alte procese. – amânat: inseamna întreruperea executarii procesului un anumit timp. Trecerea de la starea gata de executare la starea in curs de executare are loc cand un procesor il alege pentru executare. Se cere insa foarte multa atentie la folosire. se asteapta pentru completare si apoi se continua cu urmatoarea linie de cod. Un fir de executie (thread) este un program secvential. Un proces în curs de executare poate fi suspendat (amanat sau blocat). Un proces poate avea mai multe fire de executie. va fi folosit doar unul singur. . iar problemele care pot aparea pot fi foarte greu de rezolvat. in timp ce un alt thread le prelucreaza pe cele existente). Scrierea unui cod multithread este complexa. Programul nu poate raspunde actiunii unui utilizator in acest timp si chiar in cazul mai multor procesoare. La terminare. el poate executa mai multe fire de executie simultan. aceasta procedura are un singur parametru de tip întreg. poate avea mai multe stari. care poate fi executat concurent cu alte fire. datorita programarii single-thread. in timp ce thread-urile impart aceeasi memorie (heap) cu alte thread-uri care ruleaza in aceeasi aplicatie (un thread poate prelua informatii noi. el numindu-se multithread.Esential in .Intr-un program liniar se executa o singura linie de cod. thread. dupa care poate reveni în substarea gata de executare. trece in starea terminat. Un fir de executie. Diferenta dintre un proces si un thread este ca procesele sunt izolate total unul de celalalt.

Start().folosirea firelor de executie multiple este evitarea conflictelor de resurse.i).numara :{1}". pentru ca avem doar unul. i++) { Console. i++) { Console. //obiectul Thread Thread thread1 = new Thread (new ThreadStart(numara. al carui constructor va cere ca parametru un delegate de tipul ThreadStart. Thread thread2 = new Thread(new ThreadStart(numara.Zece)). O sa adaugam inca un thread.Name = "Thread Two". for (int i = 0.WriteLine("Simple Thread"). //obiectul Thread Thread thread1 = new Thread (new ThreadStart(numara. thread2.Start().WriteLine(i). Adaugam namespace-ul. } } } in Main: Numara numara = new Numara(). thread1.Thread. Cel mai simplu mod de a crea un thread este sa instantiem un obiect Thread. cand vor trebuie blocate anumite resurse. pe rand. o sa setam numele pentru o identificare mai usoara si vom folosi proprietatea CurrentThread care va returna firul de executie curent.WriteLine("{0}. thread1. i <= 10. Exemplu pentru un simpu thread: class Numara { //numara pana la 10 public void Zece() { Console. mai intai: using System.Start(). Codul de mai sus nu reflecta puterea firelor de executie multiple.CurrentThread. .Name = "Thread One". i <= 10.Threading.Zece)). thread2. threaUnu.Zece)). pentru a putea fi folosite de catre un singur fir de executie. public void Zece() { for (int i = 0.Name. Delegatul va indica ce metoda va rula in thread.

Zece)) }. Proprietatea Priority . Metoda Sleep Se foloseste atunci cand vrem sa suspendam un fir de executie. pentru o anumita perioada.Sleep(5000). Metoda Join Presupunem ca suntem in situatia cand vrem ca un thread sa astepte un alt thread sa isi termine executia. Metoda primeste ca parametri un integer care reprezinta numarul milisecundelor cat va fi suspendat firul de executie. inainte ca thread-ul nostru curent sa continue.Join().Zece)).Abort(). va contine cod care va arata cum thread-urile apeleaza metode diferite. //se va merge mai departe cu executia programului //dupa terminararea celor trei fire de executie thread1. de la sfarsitul articolului. new Thread(new ThreadStart(numara. Exemplu: Intr-una din metodele de mai sus adaugam : Thread.} } Exemplul complet.Join(). Thread[] threads = { new Thread(new ThreadStart(numara.Join(). thread3. Cand trebuie sa declaram mai multe fire de executie. //thread2 a fost oprit thread2. Metoda Abort Se foloseste atunci cand vrem sa oprim (“kill”) un fir de executie. thread2. putem construi un vector de fire de executie.

fiind suficient doar : //declare ArrayList lista = new ArrayList(). //folosim iteratia pentru //parcurgerea listei foreach (object o in lista) { Console. Clasa ArrayList este continuta in spatiul de nume System. dar acest lucru poate incetini executia programului. va fi aruncata o exceptie : .Add(5. AboveNormal. La declarare nu trebuie sa ii specificam marimea.WriteLine("Lista are {0} obiecte". //Folosind metoda Add adugam obiecte.Collections. BelowNormal.Net.65). il va tine “ocupat” pana la incheiere. } //proprietatea count //pentru a afla numarul de elemente //din lista Console. Aceasta clasa ne permite sa construim un vector care sa creasca in marime. Folosirea firelor de executie permite rularea proceselor simultan. lista. cea a sincronizarii: mai multe fire de executii acceseaza acelasi obiect. indiferent de tipul lor. ArrayList ArrayList este o colectie simpla care poate stoca orice tip de obiect. Codul folosit in exemplele de mai sus poate fi descarcat aici. Daca incercam o iteratie astfel. lista. Normal. simulan.Folosind aceasta proprietate. fie prin folosirea unor caracteristici ale .Net care creeaza implicit thread-uri: BackgroundWorker. adaugand mereu elemente noi. Solutia vine de la “lock”: atunci cand primul thread acceseaza obiectul. thread pooling sau la construirea unui Web Service sau unei aplicatii Asp.Count). daca nu sunt folosite cu atentie. Highest } In lucrul cu multithreading-ul apare o problema majora. O aplicatie C# poate deveni multi-threading in doua moduri: fie explicit prin crearea si rularea firelor de executie.Add(3).WriteLine(o). se poate determina ce timp de executie are un thread in comparatie cu alte threaduri active din acelasi proces: enum ThreadPriority { Lowest.Add("String"). //adaugam obiecte lista. lista.

//sortare in ordine alfabetica listaString.String'. foreach (object o in listaString) { Console.BinarySearch("def")).Add("ghi ").foreach (string s in lista) { Console.Int32' to type 'System.ToString()). } Unable to cast object of type 'System. Pentru localizarea unui anumit element.Add("xyz"). listaString.WriteLine(listaString.Sort(). apelam metoda BinarySearch si transmitem valoarea obiectului pentru a fi returnata pozitia obiectului in lista. listaString. foreach (object o in listaString) { //convertim in string Console.ToString()).Reverse().Remove("abc").WriteLine(o.WriteLine("----"). listaString.Add("abc").WriteLine(s). ArrayList si Array se aseamana foarte mult. listaString.Add("def"). Putem folosi si metoda Contains care va returna o valoare de tip boolean ( daca lista contine sau nu contine elementul cautat). Console.WriteLine(o. ArrayList cu referinte . } Console. Ambele permit stocarea unui numar mare de elemente. //sortare in ordine inversa listaString. listaString. //sterge un obiect //din lista lista. } Folosim metoda Remove pentru a sterge un obiect din lista. Construim o lista de tip string si vom folosi metoda Sort pentru a o sorta alfabetic si Reverse pentru sortare inversa ArrayList listaString = new ArrayList().WriteLine(listaString.Contains("def")).Add(" "). Console.

} In Main: //initial putem dam un parametru //dar poate pastra mai multe //sau mai putine elemente ArrayList conturi = new ArrayList(10). } //afiseaza soldul public decimal Sold() { return sold.Add(student). Observatie : nu adaugam un Cont in lista.suma. Deci. Cont elev = new Cont(). ci o referinta. vom avea eroare la compilare : . } } //adauga suma la debit public void Depune(decimal suma) { sold = sold + suma. nu se adauga obiectul insusi. //scade o suma din sold public bool RetrageSuma(decimal suma) { //daca nu sunt suficienti bani if (suma > { return } else { sold = return } sold) false. cum suntem obisnuiti. //adaugam referinte conturi. //creem instante ale clasei cont Cont student = new Cont(). ci doar facem ca un element din lista sa indice catre un Cont.Add(elev). class Cont { private decimal sold = 0. true. cu 3 metode. Apoi vom construi obiecte pe baza ei si vom adauga referinte in ArrayList catre obiectele respective.Vom crea o clasa Cont. Cum accesem elementele ? Daca incercam astfel. conturi. sold .

Impreuna cu alte colectii din . si nu la executie (run-time). An explicit conversion exists (are you missing a cast?)”.Sold()). in plus avand avantajul de typesafe. lucru care permite ca unele eventualele erori sa fie returnate la compilare (acest lucru face ca programul sa fie stabil.WriteLine(c.Cont c = conturi[0]. c. de tipul: “Cannot implicitly convert type ‘object’ to ‘ContExemplu. Vom rezolva problema convertind la tipul Cont. o colectie tipizata.rar Clase generice Reamintesc problema din articolul despre ArrayList: cream o lista in care adaugam referinte catre obiecte iar pentru a le accesa trebuia sa convertim explicit la tipul obiectului. doar ca implementarea si regulile de utilizare difera in . Console.Net.Sold(). in sensul ca mare parte dintre errorile datorate tipurilor de date folosite sunt detectate la compilare). . Cannot implicitly convert type ‘object’ to ‘ContExemplu. O lista cu membrii ArrayList se gaseste pe msdn.Exista si StringCollection. Notiunea de cod generic poate parea cunoscuta celor care programeaza in C++. Conceptul de generics a aparut in versiunea 2.Cont’. Am expus aceasta problema.rar ListaVectori. aceste clase tipizate sunt usor de folosit in dezvoltare datorita faptului ca Visual Studio poate face automat validarea si nu mai e nevoie sa folosim conversia. C# este un limbaj type-safe. Codul folosit in exemplele anterioare: • • ContExemplu. Foarte asemanatoare cu ArrayList este clasa List. An explicit conversion exists (are you missing a cast?) Motivul este ca ArrayList este o lista de Objects. altfel primeam eroare la compilare.0 a limbajului C#. //facem conversie la Cont Cont c = (Cont)conturi[0]. pentru a intelege mai bine termenul de generic.Cont’.Net care sunt strongly typed. Clasele sau functiile generice sunt cele care primesc ca parametru tipul datelor manipulate si sunt foarte folosite in implementarea colectiilor sau algoritmilor care actioneaza asupra unor tipuri variate de date. Vom scrie despre aceasta clasa in articolul viitor.

Add(student). foarte simplu : Exemplu<int> ex = new Exemplu<int>().Capacity). astfel ca. conturi[0]. clasele generice vor contine intre “<” “>” tipul parametrului. List<int> lista = new List<int>(4).Depune(40). Proprietatile Count si Capacity Aceste proprietati furnizeaza informatii despre obiectul de tip List. lista.Generic.Count). Lista conturi “va sti” exact ce tip de obiecte sa stocheze. identifica numarul de elemente existente in lista. //va afisa 4 Console.Cont’ Cu clasa List se pot face operatii asematoare cu cele din ArrayList (Add. conturi. List<Cont> conturi = new List<Cont>(). BinarySearch etc). Exemplu<double> ex2 = new Exemplu<double>().Generic.WriteLine(conturi[0]. la declarare. Count.WriteLine(lista.Collections. . Remove.Add(10). putem construi o clasa pentru int si una pentru double. inainte de a o folosi. vom adauga : using System. Console. Proprietatea Capacity arata cate elemente mai pot fi adaugate in lista fara ca aceasta sa fie redimensionata. va aparea eroare de compilare: Argument ’1′: cannot convert from ‘int’ to ‘List. ca si in cazul ArrayList. Daca incercam sa adauga un o varabila de un alt tip in afara de cel specificat in “<>”.Collections. astfel: Cont student = new Cont(). astfel vom putea adauga un obiect de tip Cont si vom putea accesa metodele lui. public class Exemplu<T> Acum. construim o lista in care vom retine referinte catre obiecte de tip Cont.Dupa cum se va observa in cazul clasei List.WriteLine(lista. Folosind aceeasi clasa Cont din articolul ArrayList. Clasa List se gaseste in spatiul de nume System.Sold()). //va afisa 1 Console. Proprietatea Count.

Capacity). 4.Evident. //sunt egale Console. vom prezenta o alta clasa. . Console. Console. Copierea unui vector intr-o lista Presupunem ca avem un vector si vrem sa construim o lista care sa contina elementele acestuia. Dictionarele stabilesc o relatie (“map“) intre o cheie si o valoare. care lucreaza tot cu grupuri de obiecte.Clear().TrimExcess(). De exemplu. type-safety. 6 }. //copiem elementele vectorului in lista List<int> lista = new List<int>(vector). 5. //sterge elem din lista conturi. se foloseste metoda TrimExcess(). avem numarul de identificare al unui angajat. reducerea operatiilor de boxing. lista. Apelul acestei metode este similar cu atribuirea liste catre null sau cu instantierea unui nou obiect (= new List…) in locul celui ale carui componente le dorim sterse. Codul generic aduce un plus de performanta si calitate programelor scrise in C#. Dictionary.WriteLine(lista. Exemplu: //creem un vector de int int[] vector = new int[] { 3. avand rolul principal de stabili o relatie intre o cheie si o valoare.Count). In articolul urmator.WriteLine(lista. rezultatul returnat de proprietatea Capacity va fi intotdeauna mai mare decat cel returnat de proprietatea Count.WriteLine(lista. caruia ii putem atribui un obiect care reprezinta angajatul. Vom transmite vectorul ca parametru iar lista va copia elementele din el.Net este Dictionary. Dictionary O alta colectie generica utila in . Notiunea de generic a fost adaugata in C# pentru evitarea conversiilor. In cazul in care se doreste eliminarea acestei diferente. O lista cu membri clasei se gaseste pe msdn. Metoda Clear Metoda Clear va elimina toate elementele din List Conturi.Count). Ea functioneaza pe principiul perechilor cheie/valoare.

Cont’“.contStudent).Add("Elev". Cont contProfesor = new Cont().Generics. se recomanda mai intai testarea cheilor pentru a vedea daca exista si de a evita primirea exceptiei. //dictionar de tip string/Cont Dictionary<string. Metodele ContainsKey. //exceptie dictionar["a"]. Daca nici un element nu are o valoare pentru cheia respectiva. ContainsValue Adaugam mai multe elemente in dictionar: Cont contElev = new Cont().Depune(50). nu apar probleme de conversie: dictionar["Student"]. //eroare MyClass cls = new MyClass(). daca vom incerca sa adaugam o valoare de alt tip decat Cont.Clasa generica Dictionary face parte din spatiul de nume System. Va aparea eroare la compilare. dictionar.Add("Student". folosita in articolele despre ArrayList si List<T>. contElev). In cazul folosirii clasei Dictionary. construim un dictionar care va stoca perechi cheie/valoare de tipul string/Cont: //instanta a clasei Cont Cont contStudent = new Cont().ContainsKey("aa")) { .Collections. dictionar.Collection. Pentru folosirea ei. Folosind in continuare clasa Cont. folosind metoda ContainsKey.Cont> dictionar = new Dictionary<string.Add("Profesor".MyClass’ to ‘Dictionary. contProfesor). La accesarea unui element.Add("String". “cannot convert from ‘Dictionary. if (dictionar. Incercam sa accesem cu ajutorul unei chei un element.Generic.cls). va aparea exceptia KeyNotFoundException : “The given key was not present in the dictionary”. //adaugam un element in dictionar dictionar.Depune(50). dictionar. vom folosi: using System. Cont>().

out cont)) { Console. int> catalog = new Dictionary<string. cont. contElev.Add("Produs1".Sold()). } Construim un dictionar un pic mai simplu. Clasa Dictionary contine o metoda.ContainsValue(contElev)) { Console. . int>().WriteLine("sold {0}". in cazul in care este gasita.TryGetValue("Elev".WriteLine("exista").WriteLine("nu exista"). 200). if (dictionar. } Metoda TryGetValue TryGetValue va returna valoarea asociata unei chei.. Daca nu este gasita. //creem o instanta de tip Cont //pentru a putea fi returnata valoare Cont cont = new Cont()."). care cauta in toata colectia dupa valoare data ca parametru: //cautare dupa valoare if (dictionar. ContainsValue. } else { Console. Exemplu: Ca sa testam daca metoda va returna corect valoarea cheii cautate. Folosirea acestei metode este eficienta atunci cand se doreste obtinerea valorilor dintr-un dictionar unde programul acceseaza frecvent chei care nu sunt in dictionar. catalog..} else { } Console.").WriteLine("Exista. pentru a arata cum putem folosi KeyValuePair intrun ciclu foreach.Depune(40)..WriteLine("Nu exista.. Metoda are doi parametri: cheie – a carei valori incercam sa o obtinem si valoare – contine valoarea asociata cheii respective. Console. Dictionary<string. pentru a modifica valoarea soldului. apelam metoda Depune. va returna valoare implicita pentru tipul valoare.

} Pentru stergerea tuturor perechilor cheie/valoare din dictionar. care va avea ca parametru o cheie. pereche. :{0}". aceasta poate cauza probleme in cazul unui numar foarte mare de elemente. se utilizeaza proprietatea Count. organizata pe baza unui cod “hash” al cheii) . atunci cand se doreste construirea unei copii a unui dictionar existent. O colectie inrudita cu Dictionary este SortedDictionary. elem. int> pereche in catalog) { Console.catalog.Value).{1}".WriteLine("{0}. HashTable. pereche.Clear(). //eliminarea unui element dictionar. unde perechile sunt sortate dupa cheie.Value). } Un lucru util in folosirea clasei Dictionary.Key. 150). int>(catalog). O lista cu membrii clasei Dictionary. in .Remove("Elev").WriteLine("Nr. //construim o copie //a unui dictionar existent Dictionary<string. foreach (KeyValuePair<string. se foloseste metoda Clear. Console. In urmatorul exemplu vom realiza o copie a dictionarului catalog. probabil va aparea intrebarea : Care trebuie utilizata si cand? Recomandarea e ca Dictionary sa fie folosit atunci cand e nevoie de cautari (“lookups”). sunt: HashTable (colectie de perechi cheie/valoare. folosim metoda Remove. In cazul unei cautari in clasa List. int> pereche in copie) { Console. int> copie = new Dictionary<string. Exista colectia non-generica. pereche.{1}". dictionar. dictionar.Net Framework. Daca se doreste eliminarea doar a unui element. 230). //afisam elementele din dictionar foreach (KeyValuePair<string. este folosirea constructorului.se gaseste pe msdn. care functioneaza la fel ca Dictionary. Pentru a afla numarul de elemente.Count). cu exceptia faptului ca opereaza pe tipuri object.Key. pereche.Add("Produs3". In urma articolelor despre List si Dictionary.WriteLine("{0}. Alte clase care se bazeaza pe dictionare. catalog.Add("Produs2".

iar cand numarul elementelor va creste. Mai intai. Colectiile generice dau foarte mult flexibilitate si sunt recomandate inainte celor non-generice.ToString().string>: //declarare obiect de tip Dictionary Dictionary<int. NameValueCollection (dictionar de perechi nume/valoare. HybridDictionary (dictionar care se bazeaza pe ListDictionary cand numarul elementelor este mic.ReadKey(). va folosi HashTable). il returneaza functiei principale if (int. Vom alege un proiect de tip Console Application si vom explica notiuni care nu au fost introduse pana acum. Dupa crearea lui. care va avea CreeazaDictionar. string> catalog = null. //functia de preluare a caracterelor de la tastatura public int NumarElemente() { //cat timp vor fi introduse caractere de la tastatura while (true) { //retinem caracterul char ch = Console. SalveazaDictionar. Construim clasa DictionarExemplu. Tipul Dictionary este util in situatiile cand e nevoie de stocarea obiectelor pe baza unui identificator unic. dictionar care va fi construit pe baza a ceea ce introduce utilizatorul de la tastatura. il vom salva intr-un fisier text pe hard. //daca e numar. Apoi vom citi colectia din fisierul text. declaram un obiect de tip Dictionary<int. StringDictionary ( un “hashtable” cu perechi cheie/valoare doar de tip string). in interiorul clasei.SortedList (perechi cheie/valoare care sunt sortate in functie de chei si care sunt accesate de cheie si index). ca metode NumarElemente. //vom retine numarul in aceasta varabila int result.KeyChar. vom lucra un exemplu in care vom folosi o colectie. elementele pot fi accesate prin nume sau index). ListDictionary (dictionar optimizat pentru colectii mici de obiecte. In acest articol. un dictionar cu perechi de chei de tip int si valori de tip string. cu mai putin de 10 elemente). CitesteDictionar. Acest obiect catalog va fi folosit in metodele CreeazaDictionar si SalveazaDictionar. out result)) { .TryParse(ch.

CreateText("C:\\dictionar. nume).WriteLine("Nume pentru persoana {0}".Write("(" +el."). iar daca va gasi numar. //parcurgem dictionarul foreach (KeyValuePair<int. i < numarPersoane. fara a depasi numarul maxim de elemente. .V>).txt"). fisierIesire. Intr-o iteratie.Add(i. } Console. i++) { Console.ReadLine(). string>(). } Console. il va returna functiei Main. //numarul de elemente va fi egal cu numarul primit de la tastura for (int i = 0.")."). } Metoda CreeazaDictionar va primi ca parametru numarul de elemente returnat de functia NumarElemente si care va reprezenta numarul de elemente al dictionarului. numarPersoane.WriteLine(el. Vom afisa un mesaj de confirmare dupa construirea dictionarului. //retunreaza numarul return result. i). string nume = Console. //functia pentru construirea dictionarului public void CreeazaDictionar(int numarPersoane) { catalog = new Dictionary<int.WriteLine("Dictionarul a fost creat. string> el in catalog) { //scriere textului in fisier fisierIesire.Close().} } } Console.WriteLine("Dictionarul a fost salvat in fisier text. //adaugam in dictionar iteratia la care a ajuns i //si numele primit de la tastatura la iteratia respectiva catalog. } //inchiderea fisierului fisierIesire. va prelua caracterele introduse de utilizator. vom adauga cate un element dictionarului catalog cu ajutorul functiei Add (vezi articolul despre Dictionary<K. Pe acest numar il vom folosi pentru a sti cate elemente va avea dictionarul pe care vrem sa il construim. Aceasta metoda din clasa DictionaryExemplu. //functia salveaza dictionarul intr-un fisier public void SalveazaDictionar() { //creeaza fisierul la calea pe StreamWriter fisierIesire = File.WriteLine("").Value+")").Key+".

CreeazaDictionar(numarElem). declaram si instantiem clasa DictionarExemplu: DictionarExemplu dictionarExemplu = new DictionarExemplu(). va deschide fisierul text a carei cale a fost transmisa ca parametru metodei OpenText. Daca vom naviga la acea cale.SalveazaDictionar(). //cat timp linia citita nu este goala while ((x = fisierIntrare. Daca se doreste citirea dictionarului din fisierul text in care a fost salvat: dictionarExemplu.Close(). Console.txt si va scrie in consola fiecare sir de caractere gasit. Preluam numarul de elemente primit de la utilizator: int numarElem = dictionarExemplu. la calea data ca parametru metodei CreateText. Vom transmite numarul functiei responsabila cu crearea dictionarului: dictionarExemplu. } //inchidem fisierul fisierIntrare. care va contine colectia catalog.ReadLine()) != null) { //scrie in consola Console. } Metoda CitesteDictionar. din acelasi spatiu de nume. .IO. //definim o variabile string care va parcurge fisierul pana la final string x.Metoda SalveazaDictionar va salva dictionarul catalog creat de metoda CreeazaDictionar si cu ajutorul clasei StreamWriter din spatiul de nume System.WriteLine(x). cu ajutorul clasei StreamReader. System. despre care vom discuta intr-un viitor articol.txt. dictionarul catalog va fi salvat sub forma unui fisier text.txt").OpenText("C:\\dictionar. vom gasi un fisier text.IO. apoi va parcurge fisierul dictionar.").CitesteDictionar(). Daca se doreste salvarea dictionarului creat in format txt pe hard: dictionarExemplu.NumarElemente().WriteLine("Dictionarul a fost citit din fisierul text. //citeste textul dintr-un fisier public void CitesteDictionar() { //deschidem fisierul pentru a citi din el StreamReader fisierIntrare = File. cu numele dictionar. In metoda Main din clasa Program a proiectului.

IO contine clase care pot fi folosite la exploatarea. afisarea subdirectoarelor. decompresarea datelor. vom prezenta interfata IEnumerator. Console. data logging. } Aceasta clasa ajuta la furnizarea multor informatii cu privire la directoare: nume. In articolul viitor.WriteLine(subDir. troubleshooting. marime. MoveTo (muta directorul si continutul sau la o alta cale). GetFiles (returneaza lista de fisiere continute in directorul respectiv). am construit si o functie care sa citeasca dintr-un fisier text. Clasele DirectoryInfo si Directory Aceasta clasa contine metode statice pentru crearea. Pentru a descarca in format rar codul integral folosit in articolul curent – click aici! System. din cele prezentate in articolele precedente. Metodele uzuale sunt Create (creeaza un director). DirectoryInfo di = new DirectoryInfo(@"C:\Windows").Acesta a fost un exemplu scurt. //afisam in consola fiecare director din vector foreach (DirectoryInfo subDir in subDirs) { Console.IO: using System. System. practic. De asemenea. comunicarea cu alte aplicatii. List sau ArrayList) si salvarea ei sub forma unui fisier text.IO. administrarea fisierelor si directoarelor din sistemul de operare. CreateSubirectory. //cream un vector de obiecte DirectoryInfo //obtinute prin apelul metodei GetDirectories DirectoryInfo[] subDirs = di. data ultimei accesari. cale. pe hard. . etc). intr-o locatie specificata de noi. data crearii. continutul colectiei noastre. aplicatiile vor folosi clasele din System. compresarea. despre construirea unei colectii – dictionar (puteam alege. sa ne reamintim ce inseamna un spatiu de nume. aplicatiile au nevoie sa stocheze date pe hard-disk (salvarea intre mai multe sesiuni ale datelor aplicatiei. Alegem directorul Windows pentru a-i afisa subdirectoarele.WriteLine("Directoare").Name). Delete (sterge atat directorul cat si continutul sau). foarte simplu. Clasa nu poate fi mostenita.IO pe scurt Mai intai. De multe ori. extensii. Pentru aceasta.GetDirectories(). mutarea directoarelor.

il cream else { directorNou. Atunci cand vrem sa creem fisiere cu ajutorul programarii in C#.Create(). Diferenta este aceeasi ca si in cazul Directory si DirectoryInfo. Se intelege usor ca pentru situatiile cand e nevoie de efectuarea mai multor operatii pe un director.Create(). pe siteul Microsoft. //daca nu exista. O alta clasa folosita pentru lucrul cu directoarele din sistemul de fisiere.Exists) Console."). prin apelarea metoda unui obiect de tipul FileInfo: FileInfo fisier = new FileInfo(@"C:\DirectorTest\exempluDoi.Create(@"C:\DirectorTest\exemplu. Crearea unui fisier text: prin apelarea metodei statice File. consta in faptul ca File are metode statice care efectueaza o singura operatie asupra unui fisier. O sa cream un director(folder) nou.txt"). Console. iar metodele din FileInfo pot fi apelate pentru mai multe operatii asupra unui fisier.WriteLine("Directorul exista deja.WriteLine("Directorul a fost creat. //testam daca directorul exista if (directorNou. Nu mai este necesar construirea unui obiect care sa reprezinte directorul. este Directory. putem folosi clasele File sau FileInfo. Exemplu: //cream un director nou //constructorul clasei va primi ca parametru calea //unde va fi creat noul director DirectoryInfo directorNou = new DirectoryInfo(@"C:\DirectorTest"). copia.Descriere detaliata si membrii clasei DirectoryInfo. ."). se recomanda folosirea clasei DirectoryInfo.Create() File. sterge. vom crea fisiere pe care le vom muta. } Clasele FileInfo si File In directorul recent creat. // creeam fisierul fisier.txt"). Diferenta consta in faptul ca aceasta contine doar metode statice si se poate efectua doar o singura operatie asupra unui director. Diferenta intre ele.

txt".txt").Apelam metoda WriteAllText pentru a crearea unui fisier text. File. . scrierea unui string in el si apoi inchiderea acestuia. //filestream pentru fisierul test FileStream fisierScriere = new FileStream(@"C:\directortest\testbinar".OpenOrCreate. //cu ajutorul fileStream. Clasa FileSystemInfo Clasa FileSystemInfo reprezinta baza pentru DirectoryInfo si FileInfo. "text/copiere"). File. //variabile string sir = "text". FileMode. Aceasta clasa creeaza sau deschide un fisier. Mutarea unui fisier: File.WriteAllText(@"C:\DirectorTest\exmpluFisierScris. FileShare.txt".WriteAllText(@"C:\DirectorTest\test1. Apelam metoda Close pentru eliberarea obiectelor de tip BinaryWriter si FileStream. "text pentru test"). vom crea un obiect de tip FileStream. Mai multe detalii despre FileInfo si File. "text/mutare").txt". bw. bw.Write(numar). Clase BinaryWriter si BinaryReader Aceste clase scriu si citesc orice tip de date de baza intr-un format binar. O lista cu metodele si proprietatile ei.txt".Write(sir). obiectul binarywriter //va scrie fluxul in fisier BinaryWriter bw = new BinaryWriter(fisierScriere). aici.Write(car).@"C:\DirectorTest\test2.@"C:\DirectorTest\test2. Inainte de folosirea claselor. Nu se poate creea o instanta a acesteia.txt".WriteAllText(@"C:\DirectorTest\test1. Vom declara variabilele si le vom scrie binar. int numar = 10.Move(@"C:\DirectorTest\test1.None). Copierea unui fisier: File. File.Copy(@"C:\DirectorTest\test1. FileAccess.ReadWrite. //scriem valorile in format binar bw. char car = 'a'.txt"). pentru ca este o clasa abstracta.

Close(). //inchide si elibereaza resursele br. int numarCitit = br.BaseStream. SeekOrigin. pentru ca fiecare metoda va returna un tip de data diferit).Open. . proprietati.WriteLine(carCitit).Close(). StreamWriter si StringWriter deriveaza din clasa abstracta TextWriter. FileShare.WriteLine(sirCitit). //afiseaza in consola Console. creem din nou un obiect FileStream si apoi. FileAccess.Seek(0. //retine in variabile string sirCitit = br. Descriere detaliata a claselor FileStream. un obiect BinaryReader. Diferenta consta in faptul ca BinaryWriter are o singura metoda Write pentru scriere. char carCitit = br. StreamWritersi StreamReader sunt folosite in scrierea/citirea unui flux(stream) intr-o anumita codificare.ReadInt16(). //facem ca citirea sa aiba loc de la inceputul fisierului br.None). Clasele TextReader si TextWriter sunt clase de baza. In mod similar. FileMode. BinaryWriter.Begin). Pentru citirea fisierului binar. Functia Read poate citi tipurile de date pe care functia Write le scrie. Este recomandat ca la citirea fisierelor binare. eliberam memoria prin apelul functiei Close. Clasele StreamReader si StringReader deriveaza din TextReader. Console. StringWriter si StringReader sunt folosite pentru scrierea/citirea sirurilor de caractere in memorie. care semnaleaza evenimente atunci cand au loc modificari asupra fisierelor sau directoarelor dintr-un anumit director. FileStream fisierCitire = new FileStream(@"C:\directortest\testbinar". in timp ce BinaryReader are o metoda Read pentru fiecare tip de date (normal. clasa complementara a BinaryWriter.ReadString(). BinaryReader br = new BinaryReader(fisierCitire).ReadChar(). Dupa terminarea citirii. Console.//inchidem si eliberam resursele bw.WriteLine(numarCitit). sa se foloseasca mecanismul de “prindere” a exceptiilor (try-catch). Clasa FileSystemWatcher Aceasta clasa contine metode. BinaryReader.Read.

In articolul urmator.Renamed += new RenamedEventHandler(watcher_Renamed). FileSystemWatcher watcher = new FileSystemWatcher(). Vom fi anuntati la redenumirea oricarui fisier sau director din directortest. watcher. celelalte evenimente din aceasta clasa vor transmite eveniment de tip FileSystemEventHandler. pe msdn. //incepe urmarirea schimbarilor watcher.Deleted += new FileSystemEventHandler(watcher_Deleted). care va anunta daca un fisier dintr-un anumit director a fost. O lista detaliata cu toti membrii clasei se gaseste pe msdn.FullPath). de exemplu. Metoda indicata de delegate pentru evenimentul de redenumire va afisa fostul nume al fisierului/directorului si numele curent.IO. proprieatea IncludeSubdirectories.Exemplu: Construim un obiect de tipul FileSystemWatcher.Name).Collection.Name+" din " + e.EnableRaisingEvents = true. Este un caz singular. void watcher_Deleted(object sender. Spatiul de nume System. RenamedEventArgs e) { Console.WriteLine("A fost sters "+e. //ne anunta doar in cazul redenumirilor //delegate pentru eveniment watcher. } Se observa ca acest eveniment transmite un parametru de tip RenamedEventHandler.Path = @"C:\directortest".IO furnizeaza toate clasele necesare.OldName + " in " + e. private void watcher_Renamed(object sender. watcher. Enumerarea si compararea colectiilor . Dezvoltatorii au nevoie adesea sa acceseze fisierele si directoarele pentru a obtine informatii si a efectua modificari. pentru a urmari subdirectoare. redenumit. } Obiectul watchermai poate folosi proprietatea Filter. FileSystemEventArgs e) { Console. o sa descriu spatiul de nume System.WriteLine("Redenumit:" + e. Puteti citi mai multe despre spatiul de nume System. pentru restrangerea ariei de fisiere urmarite pentru modificari.

IEnumerable <T> si IEnumerator <T>. Se observa ca proprietatea Current nu are un comportament type-safe. Interfata IEnumerable contine o singura metoda. Daca vrem sa construim o colectie de clasa enumerabila. Obiectul returnat de aceasta metoda. putem naviga prin elementele unei colectii din element in element. daca mai exista in colectie un alt element. Toate intefetele din . Va returna true. vom folosi interfetele IEnumerable si IEnumerator pentru a folosi un foreach pentru obiecte ale clasei Cont. trebuie sa implementam interfata IEnumerable in colectia de clase si sa furnizam implementarea interfetei IEnumerator care sa fie returnata de metoda GetEnumerator a colectiei de clase. Un set nontype-safe. . cu ajutorul metodei GetEnumerator a unei colectii. Interfata IEnumerator Obiectul enumerator este folosit pentru parcurgerea elementelor din colectie (il putem privi ca un indicator care arata catre elementele dintr-o lista). este un enumerator folosit pentru parcurgerea elementelor colectiei. Framework-ul . intre cele doua. isi incep numele cu I. insa. Prin construirea unui enumerator. interfata IEnumerator<T> nu contine metoda Reset.Net Framework. In exemplul urmator. GetEnumerator. el implementand interfata IEnumerator. mai mult.} si metodele : bool MoveNext() – va directiona indicatorul catre urmatorul element din lista. Exista totusi diferente. In general. Interfata Ienumerator are proprietatea: object Current {get. prin conventie..Net Framework contine doua seturi de interfete standard pentru enumerarea si compararea colectiilor. interfata IDisposable. si prin apelarea repetata a metodei MoveNext si preluarea valorii din proprietatea Currentfolosind un enumerator. la fel cum il folosim pentru tipurile de baza. false. daca nu. IEnumerable si IEnumerator si un set type-safe. a carei metoda GetEnumerator va returna un Enumerator<T>. Una ar fi ca. La fel si in cazul interfetei IEnumerable<T>. extinzand. a carei proprietate va returna un obiect de tip T. se implementeaza si interfata asociata IEnumerator.Net pune la dispozitie interfata generica IEnumerator<T>. cand se implementeaza interfata IEnumerable. ea returnand un object. void Reset() – va returna indicatorul inapoi la primul element din lista.

this.Construim clasa Cont care va contine 3 variabile membru. private double sold.numarCurent. //constructor public Cont(int numarCurent.:" + this.Add(c). . //variabile membru private int numarCurent. string numeTitular. } //implementarea interfetei IEnumerable //va returna un enumerator public IEnumerator GetEnumerator() { return (IEnumerator)this. care va contine un vector de obiecte Cont.ToString() + "\nNume:" + numeTitular + "\nSold:" + sold. } Vom construi clasa Conturi. //variabila care va returna //pozitia curenta a enumeratorului private int pozitie = -1. numele persoanei care detine contul si soldul contului si vom creea constructorul clasei (articolul despre introducere in programarea pe obiecte). } //suprascriem functia //pentru a afisa toate variabilele membru public override string ToString() { return "Nr. private string numeTitular.numeTitular = numeTitular. numarul unic al contului. toti cei trei membri (articolul despre polimorfism).ToString().sold = sold. Clasa va contine si o metoda de adaugare in lista a obiectelor si va implementa cele doua interfete (articolul despre interfete). pe care o vom suprascrie pentru a afisa in consola pentru fiecare obiect al clasei.Crt. double sold) { this. this.IEnumerator { //construim un vector ArrayList listaConturi = new ArrayList().numarCurent = numarCurent. Mai adaugam si functia toString. //metoda pentru adaugarea unui obiect de tip // in lista public void AddEmployee(Cont c) { //adauga in lista listaConturi. //clasa Conturi //implementeaza interfetele class Conturi : IEnumerable.

AddEmployee(c3). obiectul enumerator este situat inaintea primului element al colectiei. } //nu mai sunt elemente in colectie return false. Cont c2 = new Cont(2. } public void Reset() { //pozitia initiala pozitie = -1. Construim obiectul enumerator: IEnumerator ContEnumerator = ContList.AddEmployee(c2). 3131). "Cont#1". .GetEnumerator(). ContList. return true. //cconstruim obiecte de tip Cont Cont c1 = new Cont(1. } public object Current { get { //returneaza elementul indicat de enumerator return listaConturi[pozitie]. "Cont#2".AddEmployee(c1). creem colectia: Conturi ContList = new Conturi(). 1250. //construim o colectie ContList. ContList. "Cont#3". 400).Count . Initial. } } } In functia Main.Reset(). Vom apela metoda Reset(). Cont c3 = new Cont(3.1) { //incrementam ++pozitie.} //implementarea interfetei IEnumerator public bool MoveNext() { if (pozitie < listaConturi. pentru a fi siguri de acest lucru: ContEnumerator.75).

. (incepand cu 0). Astfel. In articolul urmator.MoveNext()) { Console.IListSystem. Ele contin elemente care pot fi accesate prin valoarea asociata cheii respectivului element (pereche cheie/valoare). Exemplu: ArrayList. similar unui vector.Current). pentru ca in acelasi timp alte fire de executie pot aduce modificari colectiei. O solutie ar fi blocarea colectiei in timpul parcurgerii. altfel va aparea exceptie la executie while (ContEnumerator. Queue. Colectii pe baza de cheie Colectiile pe baza de cheie implementeaza interfata IDictionary. Vom face o analiza scurta a clasei SortedList.Collections sunt colectii non-generice. .ICollection. Colectiile din System.IO. vom discuta despre cateva clase din spatiul de nume System. Collections. Codul pentru acest articol este aici.Net pune la dispozitia dezvoltatorilor foarte multe clase pentru lucrul cu colectiile. Framework-ul .Collections.Collections. Obiectul enumerator nu are acces exclusiv asupra colectiei. vom avea o clasificare a colectiilor din framework: Colectii ordonate Aceste colectii implementeaza doar interfata ICollection si se deosebesc prin faptul ca ordinea in care elementele sunt inserate determina si ordinea in care elementele sunt regasite in colectie. parcurgerea cu ajutorul acestuia nu este thread-safe.Collections. System. } Atentie! Folosirea corecta a interfetei IEnumerator presupune mai intai apelul metodei MoveNext(). Exemplu: Stack. Acestea sunt foarte utilizate in programare.Net defineste o colectie ca fiind un obiect care implementeaza una sau mai multe interfete : System. Toate aceste clase sunt continute in spatiul de nume System. apoi accesarea proprietatii Current.WriteLine((Cont)ContEnumerator. Colectii indexate Acest tip de colectie se distinge prin faptul ca accesul la elemente se face prin index. Colectii in C# Colectiile reprezinta un mod de stoacare a obiectelor intr-o maniera structurata.Parcurgem colectia: //se invoca mai intai metoda MoveNext inainte de accesarea //Current.IDictionary.

foreach (var r in rezultat) { Console. //SAU EXCLUSIV rezultat = vectorBool. care pot fi folosite in dezvoltare. //metoda set stabileste valoarea elementului vectorBool. } Metoda And realizeaza operatia logica “AND” (articolul despre operatori in . rezultat = vectorBool. De ce? Pentru ca atunci cand . pe care am descris-o in articolul despre ArrayList. unde true este 1. care sunt sortate dupa cheie. //parcurgem tabloul foreach (bool b in vectorBool) { Console.Set(0. vectorBool. true).0 ale framework-ului.Xor(rezultat).WriteLine(r).Not(). O colectie de tip SortedList este o combinatie intre HashTable si un Array (articolul despre array).Net): BitArray rezultat = new BitArray(3). false).Exista cateva colectii importante. Elementele sunt accesate cu ajutorul cheii si al indecsilor. SortedList Aceasta clasa reprezinta o colectie de perechi cheie/valoare.WriteLine(b). true). Stack BitArray – este un vector care contine valoare de tip boolean.Set(2. } De asemenea exista si metodele Or. //Negatie rezultat = vectorBool. Folosirea acestor colectii in mod non-generic este justificata doar in cazul mostenirilor sau atunci cand se doreste compatibilitate cu versiunile mai vechi de 2. Toti membrii clasei BitArray sunt descrisi pe msdn. Xor. vectorBool.And(rezultat). //declaram un vector de tip bit BitArray vectorBool = new BitArray(3).Or(rezultat).Set(1. false este 0. Not: //SAU rezultat = vectorBool. O clasa importanta este ArrayList.

lista. Astfel. valoarea returnata va fi 5.WriteLine("Valoarea lista.GetByIndex(1)). siteul Microsoft. apoi ne vom referi la ele ca la un grup de date. ca. ghi. adica ultimul element introdus in colectie va fi primul care va iesi din colectie. elementele vor fi in ordinea: abc. primul element intrat in colectie este primul element care va iesi din colectie. 2).Add("ghi". avand posbilitatea de a le parcurge si de a le sorta. colectia se comporta ca un HashTable. . Queue Clasa Queue (Coada) este o structura de date de tipul first-in-first-out (FIFO). Pentru mai multe detalii despre clasa SortedList. va afisa 5 Console. Daca vom accesa o valoare prin index. colectia se comporta ca un Array.Add("abc". acel index va fi indicat de pozitia cheii in colectie: //va afisa 5 Console.Add("def". lista. Cand este necesar sa folosim o colectie? Folosim o colectie cand este nevoie sa “punem la un loc” o serie de elemente care sunt asemanatoare. de la pozitia a doua: " + In lista. lista. ne putem da seama usor. 9). Stack Clasa Stack (Stiva) reprezinta o structura de date de tip last-in-first-out (LIFO). 5). def. //accesem valoarea unui element.elementele acestui tip de colectie sunt accesate prin cheie folosind proprietatea Item. //construim lista si adaugam elemente SortedList lista = new SortedList(). Cand elementele sunt accesate prin folosirea unui index cu ajutorul metodelor GetByIndex sau SetByIndex.WriteLine(lista["def"]). Un exemplu cu aceasta structura vom face in articolul urmator. folosind varianta generica a clasei. Un exemplu cu aceasta structura vom face in articolul urmator. Colectiile de acest tip vor sorta elementele dupa cheie. sortate. folosind varianta generica a clasei. Adica.

la sfarsit). Un lucru foarte important este alegerea corecta. IEnumerator<T>. Mai tinem cont si de locul unde vor fi introduse noile elementele in colectie (in mijloc. performanta aplicatiei va fi afectata.Collection. Toate detaliile despre spatiul de nume System.Generic. a tipului de colectie de care avem nevoie. IList<T>. System. In ceea ce priveste clasele din cele doua spatii de nume. o corespondenta ar fi: Generic Collection<T> Comparer<T> Dictionary<K. inseamna ca avem de a face cu un numar mare de elemente. O introducere in aceasta caracteristica a C# 2. Analizam daca se vor introduce toate elementele in colectie la initializarea aplicatiei.Collection. despre List. sau daca ele vor fi stocate intr-o anumita ordine sau nu.Collections.Generic Conceptul de generic este unul foarte puternic in limbajul C#. Implicit. Stack <T> . IEqualityComparer(T).Generic contine interfete care isi au corespondente nongenerice in spatiul de nume System. Spatiul de nume System.V> List<T> SortedDictionary<K. pentru ca.V>. atunci cand apelam la colectii.0 am facut in acest articol.Collections. IDictionary<K.Pot aparea probleme de performanta in folosirea colectiilor.Collections sunt aici. sunt usor de folosit.V> Stack<T> Queue<T> ReadOnlyCollection<T> NonGeneric CollectionBase Comparer Hashtable ArrayList SortedList Stack Queue ReadOnlyCollectionBase Reamintim ca despre clasa Dictionary<K. IEnumerable<T>. sau pe parcurs.V> am scris in acest articol. IComparer<T>. Clasele din acest spatiu de nume sunt intuitive. de regula. In urmatorul articol. potrivita. produc o performanta buna. Acestea sunt: ICollection<T>. vom prezenta spatiul de nume System.

"George"))."Ion")). Ionescu).WriteLine(p. class Persoana { public string nume. Personal. vom observa ca primul element afisat este ultimul element inserat in colectie. Putem apela proprietatea Count pentru a verifica faptul ca stiva acum va detine cu un element mai putin decat inaintea apelarii metodei Pop.nume = Nume. "Paul")). stiva. public string prenume.nume). In exemplul nostru. Exista o metoda care va returna obiectul aflat “deasupra”. Popescu. ultimul introdus in stiva. public Persoana(string Nume.prenume = Prenume. . Stack<Persoana> stiva = new Stack<Persoana>(). stiva. un bun exemplu de a-mi imagina o colectie de tip stiva sunt vasele de la bucatarie care trebuie spalate. metoda Peek. } } Declaram o colectie de tip stiva. Apelam metoda Pop. foreach (var p in stiva) { Console. Daca vom afisa elementele stivei.Push(new Persoana("Ionescu". Apelam functia Push pentru a introduce elemente in stiva : stiva.Push(new Persoana("Georgescu". } Dorim sa eliminam un element din stiva. string Prenume) { this. Construim o clasa simpla Persoana si sa adaugam obiecte de acest tip intr-o stiva.Colectia de tip Stack (Stiva) este o structura de date de tip LIFO ce stocheaza elemente care pot fi apelate sau sterse printr-un singur pas. stiva. :) Clasa Stack foloseste metoda Push pentru adaugarea unui element si metoda Pop pentru scoaterea unui element din colectie. Georgescu. Afisam elementele stivei ca in modul de mai sus si observam ca elementul eliminat prin apelul metodei Pop a fost cel introdus ultimul in colectie. this. care va stoca elemente de tipul Persoana. (Popescu.Pop().Push(new Persoana("Popescu".

Un exemplu din lumea reala este “coada”. "Paul")). Ionescu.Enqueue(new Persoana("Georgescu". "Ion")). coada.nume). multimea.Enqueue(new Persoana("Ionescu". Declaram colectia: Queue<Persoana> coada = new Queue<Persoana>(). Dorim sa eliminam un element din colectie si vom apela metoda Dequeue.WriteLine(coada. "George")). . Afisam: foreach (var p in coada) { Console.Peek()). Queue<T> Clasa Queue (C0ada) este o structura de date de tip FIFO. Adica. clasa Queue are metoda Peek. coada. care va returna in acest caz. primul element intrat in colectie este primul element care va iesi din colectie.WriteLine(p. ce se formeaza la un ghiseu la banca. primul element din colectie (“de la inceputul cozii”). Putem apela proprietatea Count pentru a verifica numarul de elemente al colectiei. care acum va fi mai mic cu un element decat inaintea apelarii metodei Dequeue. } Elementele sunt afisate in ordinea in care au fost introduse. Console. Asemanator clasei Stack.WriteLine(stiva.Dequeue(). Continuam cu acceasi clasa Persoana si vom inseara obiecte de acest tip intr-o colectie Queue.Console.Peek(). primul element inserat fiind si primul afisat. coada. Clasa Queue detine metoda Enqueue pentru inserarea unui element in colectie si metoda Dequeue pentru eliminarea primului element inserat in lista. Pentru lista completa a membrilor clasei Stack.nume). site Microsoft. Adaugam cateva elemente: coada. Afisam elementele cozii ca in modul de mai sus si observam ca elementul eliminat prin apelul functiei Dequeue a fost cel introdus primul in colectie. In exemplul nostru.Enqueue(new Persoana("Popescu".

tracand o data peste lista numai pentru a . redimensionarea dinamica. C# este un limbaj type-safe.Generic. pentru a interactiona cu structuri de date variate din framework.Clear(). Alternativele sunt: ori numaream rezultatele (intr-o variabila cont). Amintim ca. coada. Am lasat la urma. poate si din cauza ca e cea mai folosita. si trebuie sa pastram intr-o lista numai persoanele cu varsta de peste 18 ani. ICollection<T>. List<T>. metode. enumerarea.Generic exista pe msdn. Nu stim de la inceput cate persoane au peste 30 de ani. sa zicem persoane. Avem o lista de obiecte. Aceasta clasa implementeaza o serie de interfete: [SerializableAttribute] public class List<T> : IList<T>. IEnumerable care permit accesul la diverse facilitati despre care voi discuta mai detaliat intr-un articol viitor. ci doar o sa enumar cateva din situatiile practice in care poate fi folositoare. sau in alte articole de pe acest blog. . Ca avantaje ale colectiilor strong type: folosirea indecsilor. pentru ca am dat anterior. Exista foarte multe clase. Pentru ca sunt foarte puternice. Ambele clase contine metoda Clear pentru eliminarea tuturor elementelor din colectie. Este alternativa la ArrayList pe care o folosesc de cand am descoperit clasele generice. Mai multe informatii despre spatiul de nume System. siteul Microsoft. atunci cand vrem sa folosim una din colectiile generice.Net are un suport foarte vast pentru colectii. stiva. Acest lucru presupune sa se stie tipul obiectului inainte de a-i atribui o valoare. in primul rand prin type safe. se recomanda folosirea cu atentie a colectiilor si alegerea corecta a tipului de colectie necesar. Nu o sa vin in cazul acestei clase cu exemple de cod. IEnumerable<T>.Collections. IList.Clear(). La ce e buna folosirea acestei clase? Din punctul meu de vedere ea este un ArrayList imbunatatit.Pentru lista completa a membrilor clasei Queue. trebuie sa declaram astfel: using System. destule exemple. List<T> este pentru mine o colectie care stie sa se redimensioneze automat pe masura ce ii adaog noi elemente si care “stie” ce tip de elemente i-au fost introduse (<T>). proprietati. ICollection. Exemple: 1.Collections.

asa ca o lista dinamica de string este solutia cea mai potrivita. System. eventual sub forma unor obiecte construite din datele de pe randul respectiv. si trebuie sa pastram numai anumite date (randuri). application (stocheaza evenimente de la toate aplicatiile care nu au deja creat un event log specific). a treia varianta pe care eu o vad este tocmai varianta care foloseste o lista generica. In urmatorul articol. 4. Avem un set de date dintr-un tabel dintr-o baza de date. care realizeaza o lista care se mareste dinamic si care permite accesul direct. obiectul accesat trebuie convertit (cast) in Person. vom descrie System. Administratorii de sistem folosesc foarte mult Windows event log. fara cast. Numarul de cuvinte definite este necunoscut. Un exemplu: sistemul de operare Windows creeaza event logs la pornire si inchidere. asa ca cea mai potrivita abordare e crearea unui obiect de tip List<string> unde sa pastram liniile de text gasite. 3.Net Framework contine spatiul de nume System. activitatile aplicatiilor si erori. 2. monitorizeaza proceselor locale. sa zicem sub forma unui DataTabel. Citim un fisier HTML si vrem sa extragem toate linkurile continute. Nu stim cate linii vom gasi. 5. Din clasa EventLog apelam metoda statica CreateEventSource. securitate (stocheaza evenimente care legate de sesiunile utilizatorilor. insa care are dezavantajul ca la fiecare accesare a unui obiect al listei. accesul la fisiere si registri). Din fiecare link construim un obiect de tip Uri pe care le pastram intr-o lista de tip List<Uri>. . la obiectele stocate in ea. un spatiu de nume care contine o serie de clase foarte interesante. Citim un fisier XML unde avem definita limba folosita de aplicatia noastra. care se redimensioneaza dinamic pe masura ce sunt adaugate personae.numara. monitorizeaza proceselor sistem din retea. altceva decat spatii goale. si trebuie sa pastram intr-un tablou toate liniile de text care contin text. un centralizator cu informatii despre sistemul de operare. Citim un fisier text. si creem un array de persoane de dimensiunea cont insa aceasta abordare presupune parcurgerea de doua ori a listei. o data pentur numarare si inca o data pentru adaugarea persoanelor cu varsta de peste 18 ani in array. alta varianta este folosirea unui ArrayList. Exista 3 tipuri de event log foarte des intalnite: system (stocheaza evenimente care nu sunt legate de securitatea sistemului). care indeplinesc anumite criterii. Evenimentele au nevoie de o sursa.Diagnostics. monitorizarea performantei sistemului.Diagnostics . List<Person>.Diagnostics. care permite interactiunea cu event log din Windows. va trebui sa avem drepturi de adminstrare asupra sistemului. iar ca sa adaugam una.

Diagnostics este performanta. elog. } Mai multe detalii despre clasa EventLog se gasesc pe msdn.Source = sursa. administratorul sistemului sau dezvoltatorul aplicatiei poate monitoriza orice aspect al performantei aplicatiei. Numarul indicatorilor difera de la sistem la sistem. elog.SourceExists(sursa)) { //daca nu.WriteLine(intrare. } Dupa ce am reusit inregistrarea aplicatiei AplicatieTest. Vom folosi PerformanceCounterCategory pentru a afisa lista categoriilor de indicatori din sistem: //GetCategories va returna lista indicatorilor //salvam toti indicatorii intr-un vector PerformanceCounterCategory[] PerformanceCounterCategory. EventLogEntryType. etc. Indicatorii sunt impartiti in categorii. Se pot monitoriza componente ca: procesoare. O alta parte importanta pe care o trateaza spatiul de nume System. accesam colectia EventLog.CreateEventSource(sursa. astfel. Un mesaj detaliat al erorilor este recomandat doar in masura in care nu se afiseaza parole.WriteEntry("Eroare". memorie. Pentru citirea evenimentelor.Entries: foreach (EventLogEntry intrare in elog.WriteLine(ind. EventLog elog = new EventLog(). detalii despre utilizatori. o creem EventLog. //parcurgem vectorul cu indicatori foreach (var ind in listaIndicatori) { Console. ca o sursa. 15).Message).Entries) { Console. listaIndicatori = . retea. Sistemul de operare Windows detine o multime de indicatori de performanta care permit monitorizarea activitatilor sistemului in timp real. in functie de hardware-ul si software-ul instalat.CategoryName). 1001.GetCategories(). conexiuni.string sursa = "AplicatieTest".Error. //verifica daca exista sursa if (!EventLog. sursa). Aceasta este masurata cu ajutorul unor contoare. putem adauga un eveniment folosind o instanta a clasei: //adaugam un eveniment la event log pentru AplicatieTest EventLog elog = new EventLog().

” inseamna computerul local) //afiseaza numele computerului pe care ruleaza procesul Console. .MachineName). //construim un obiect PerformanceCounter //care va monitoriza procesorul PerformanceCounter ip = new PerformanceCounter("Processor". Alte cateva proprietati des folosite ale clasei Process sunt: MachineName (“. "_Total").ProcessName). apeland functia statica GetProcesses (procesele rulate de alti utilizatori nu sunt vizibile intotdeauna).com.WriteLine(p. p. Console. // afisam uzura procesorului in secunda trecuta Console. Mai multe informatii despre clasa PerformanceCounter.GetProcesses()) { Console.} Pentru a monitoriza performanta cu ajutorul unui program in C#. De exemplu. unitati de stocare. vom afisa un indicator din categoria Processor. Pentru fiecare proces.WriteLine(p. Thread. folosim clasa PerformanceCounter. Pentru toate acestea. reactia la schimbari in sistem. apelam metoda Refresh.Refresh().Net Framework foloseste clasa Process si Windows Management Instrumentation. "% Processor Time". pe msdn. Aplicatiile au nevoie sa “cunoasca” aspecte ale computerului. // primul apel al metodei reseteaza indicatorul ip. ii vom afisa numele prin proprietatea ProcessName: foreach (Process p in Process. Un alt exemplu: afisam indicatorul pentru afisarea memoriei Ram disponibila: PerformanceCounter "Available MBytes").WriteLine(ip. Clasa Process Afisam toate procesele active la momentul respectiv. procesele care ruleaza la un moment dat. } Pentru ca proprietatile unui proces sa ramana actuale si valide.Sleep(1000). In acest exemplu.WriteLine(indicatorRam. .NextValue().NextValue()). indicatorRam = new PerformanceCounter("Memory".NextValue()).ProcessName+" "+p.

WriteLine(p. //.BasePriority //afiseaza numele si prioritatea procesului Console.BasePriority).FileName = "notepad. stopWatch. Event Viewer.Diagnostics.. . am ales sa discutam despre: Event logging – este o modalitate centralizata pentru a inregistra evenimente software si hardware importante pentru aplicatie. Pentru o privire detaliata asupra clasei Process vizitati siteul Microsoft.. Modul de folosireeste simplu: using System. Stopwatch stopWatch = new Stopwatch()... Astfel. notepad. Asemenea informatii sunt utile in instalarea/configurarea aplicatiei.exe".Stopwatch – din puctul meu de vedere cea mai folosita clasa a acestui namespace la nivel de practica: oricine are nevoie. sa stie cat timp dureaza executia unui anumit bloc de aplicatie.Diagnostics. //blocul de cod a carui timp de executie vrem sa il masuram stopWatch.. Ca sa scurtez povestea: Stopwatch e o clasa care permite masurarea timpului scurs intre doua puncte ale aplicatiei. in cadrul spatiului de nume System.Diagnostics. Ea este influentata direct de calitatea codului scris pentru aplicatie.Stop(). Despre toti membrii spatiului de nume System. se pot face modificari majore sau minore asupra codului pentru a mari viteza de executie. Clasa Process pune la dispozitie metoda statica Start. Pentru incheiere am pastrat ceva special: System. Performanta – se refera la viteza executiei unui program.Start(). se poate defini ca o aplicatie care ruleaza. O recomandare este stabilirea unor puncte de performanta si monitorizarea ei in cursul dezvoltarii aplicatiei. Sistemul de operare Windows expune foarte multe informatii despre computer si despre el insusi prin intermediul WMI.Start(). puteti afla pe siteul msdn. Proces – in termeni generali.Diagnostics. Ca un rezumat al articolului. notepad.StartInfo. pentru a porni un nou process. Nu trebuie decat sa ii specificam numele fisierului executabil: Process notepad = new Process().. Windows furnizeaza o interfata utilizator pentru vizualizarea log-urilor. la un moemnt data. Un thread (fir de executie) este unitatea de baza pe care sistemul de operare o aloca procesului.com.ProcessName + " " + p.

O functie Hash nu este inversabila.WriteLine("Executia a durat: " + stopWatch... Informatiile obtinute despre timpul de executie al anumitor portiuni – blocuri – de cod sunt. care depinde de tipul algoritmului folosit si nu de cantitatea (lungimea) datelor de intrare. Utilitatea acestui tip de masuratoare depinde de la aplicatie la aplicatie. Modificari minore in blocul de date duce la aparitia de modificari nepredictibile si importante in valoarea hash calculata. La fel si pentru webservice. sa generez un grafic imi ia 80 milisecunde. Valoarea hash are o lungime fixa indiferent de lungimea datelor pentru care a fist calculata. cand scrii o aplicatie. Daca scriu loguri. Functiile hash sunt folosite in semnaturi digitale sau pentru verificarea integritatii datelor. este imposibila gasirea prin intermediul unui calcul a unui alt bloc a carui valoare hash sa fie aceeasi.ElapsedMilliseconds + "milisecunde") //. alt loc unde am folosit este pentru o aplicatie care genereaza niste grafice pe baza unor date care vin dintr-un webservice si trebuie sa generez la fiecare incarcare a unei pagini web un numar nedefinit de grafice – intre zero si cateva zeci.... Valoarea hash a doua blocuri de date ar trebui sa fie identica daca cele doua blocuri de date sunt identice. un alt bloc de date care sa aiba aceeasi valoare hash. daca iti ia 1 secunda sa citesti ceva din baza de date sau daca iti ia o milisecunda. de obicei de dimensiune fixa.Console. atunci scriu si informatii despre timpul de executie. am folosit ceva asemanator pentru a verifica timpul necesar unei aplicatii care imi genereaza documente pdf online pentru un document. Cat timp imi trebuie pentru a genera 40 de grafice? Daca e 80 milisecunde x 40 ar trebui sa mai lucrez la algoritm! Un alt exemplu de folosire a acestei clase este penru optimizarea (sau el putin cunoasterea) problemelor de conectare la o baza de date sau la un webservice. O functie hash are (ar trebui sa aiba) urmatoarea proprietate: este imposibil de gasit. Sau cu alte cuvinte. In articolul urmator vom discuta despre spatiul de nume System. E important sa stii. HASH O functie hash este o procedura bine definita sau o functie matematica ce converteste o cantitate de date de dimensiuni varibile intr-o secventa de date de dimensiuni mici. in cazul meu cel putin. .Text. in practica.. Este imposibila reconstituirea satelor care au generau o anumita valoare hash. prin calcule. Cu alte cuvinte. Mai important decat masurarea duratei unei operatii este insa masurarea diferentei de timp intre executarea codului o data si de 100 de ori. daca pentru un bloc se date dat calculam valoarea hash. informatii care ajung in logurile aplicatiei. Eu.

case HashAlgoritm. Pentru inceput am construit un enum. derivate din HashAlgorithm care implementeaza 4 lgoritmi de criptare: SHA1. // Initialize the hashing algorithm class. HashAlgoritm hashAlgorithm) { // plain text to a byte array. incat nu o sa pun screenshoturi sau codul care il defineste. case HashAlgoritm. folosita ca baza pentru diversi algoritmi de hash. SHA512 } Aplicatia exemplu este o aplicatie winform. SHA512.UTF8. Operatia de criptare va avea loc la apasarea butonului.SHA256: hash = new SHA256Managed(). break. Al doilea textbox va afisa stringul encriptat folosind algoritmul ales din comboBox.Net. SHA384Managed si SHA512Managed. HashAlgorithm este o clasa abstracta. un comboBox si un buton.SHA384: hash = new SHA384Managed(). HashAlgorithm hash.. si cu ajutorul caruia userul va putea alege functia de hash dorita: public enum HashAlgoritm { SHA1. in namespace-ul System. SHA384. break. In exemplul pe care vreau sa il prezint aici o sa folosesc 4 clase. byte[] textToHashBytes = Encoding. .GetBytes(textToHash). Form-ul e atat de simplu. Primul textbox va fi locul unde userul poate introduce un text pe care vrea sa il cripteze. switch (hashAlgorithm) { case HashAlgoritm. SHA256.Security. SHA256Managed.Cryptography contine o serie de clase care implementeaza divesi algoritmi hash. SHA384.SHA512: hash = new SHA512Managed(). Functia care face criptarea este urmatoarea: public static string ComputeHash(string textToHash. break. care contine 2 textbox-uri.SHA1: hash = new SHA1Managed(). Aceste clase sunt: SHA1Managed. SHA256. break. case HashAlgoritm. in care am introdus cei 4 algoritmi pe care il voi folosi.

return hashValue. Exemplu: vom creea doua siruri de caractere (pe primul il vom considera expresie regulata) si vom determina daca primul sir de caractere se va potrivi cu al doilea sir de caractere.WriteLine("Expresia regulata:").ComputeHash(textToHashBytes). Deasemeni.ReadLine(). pentru a fi reprezentat ca string se foloseste Convert.WriteLine("Potrivire!"). Console. Acesta trebuie sa fie validat.default: hash = new SHA1Managed(). // Convert the result into a base64-encoded string. asa cum se observa din cosul de mai sus. if (Regex.WriteLine("String pentru comparare:"). rezultatul criptatii este tot un array de biti. string stringC = Console.Text Dezvoltatorii au nevoie foarte des de a procesa text pentru ca interactiunea aplicatiei cu utilizatorul se bazeaza pe introducerea textului. else Console. siruri de caractere doar cu litere mici. Exemplu: stringuri care au numere. motiv pentru care textul este “convertit” in byte[]. Apelam metoda IsMatch din clasa Regex pentru a verifica daca cele doua siruri de caractere se potrivesc.RegularExpressions(link).WriteLine("Nepotrivire!").Text. Adaugam declaratia de utilizarea a spatiului de nume System. } Criptarea. reformatat. O expresie regulata mai poate fi utila in extragerea/inlocuirea unor portiuni de text. care. se aplica pe array de biti. O expresie regulata reprezinta un set de caractere care este comparat cu un string pentru a determina daca string-ul respectiv indeplineste cerintele unui anumit format. // Return the result. break. string hashValue = Convert.ReadLine(). expresieRegulata)) Console. string expresieRegulata = Console. } // Compute hash value for the text byte[] hashBytes = hash. . Construim cele doua siruri: Console.ToBase64String(hashBytes). siruri cu format hexadecimal.ToBase64String System.IsMatch(stringC.

O lista cu standardele de codificare UNICODE poate fi gasita pe siteul unicode. expresia regulata va fi: string expresieRegulata = "^\\d{5}$". Aceasta inseamna ca stringul va trebui sa aiba fix 5 caractere ({5}) si acestea trebuie sa fie doar cifre (\d). Formatul UNICODE furnizeaza pentru fiecare caracter cate un numar unic. cand este nevoie de a controla procesele de codificare si decodificare – interoperabilitatea cu sistemele UNIX care folosesc alte tehnici de codificare. Inceputul sirului de caractere este marcat de ^ si $ reprezinta sfarsitul sirului. // codificarea Korean Encoding codificare = Encoding. De cele mai multe ori.Text contine clase pentru codificarea si decodificarea caracterelor.Net Framework. Consideram expresia regulata ^\d{5}$ .Functiei IsMatch ii mai putem adauga un parametru reprezentand o enumerare a optiunilor cu privire la modul in care se face potrivirea – RegexOptions(link).:P Sunt foarte greu de utilizat daca nu sunt cunoscute bine.GetEncoding("Korean"). de program sau de limba. .org. i < codat. . Fiecare sir de caractere dintr-un text este codificat folosind unul din standardele de codificare. insa reprezinta o metoda eficienta in validarea informatiilor introduse de utilizator. i++) Console.Net Framework utilizeaza Unicode UTF-16 pentru reprezentarea caracterelor. Codul ASCII este fundamentul pentru tipurile existente de codificare. vizitati msdn. codat = codificare. Expresiile regulate pot creea foarte multa confuzie.GetBytes("Test!"). // Convert ASCII bytes to Korean encoding //convertim bytes ASCII in Korean byte[] codat. codat[i]). i. Un exemplu de folosire a clasei Encoding este convertirea caracterelor in bytes. indiferent de platforma. // afiseaza codurile bytes-urilor for (int i = 0.WriteLine("Byte {0}: {1}". mai ales la citirea lor. Sunt situatii. Spatiul de nume System.Length. Revenind la exemplul anterior. iar stringul care va fi comparat cu aceasta va fi compus din 5 numere. acest lucru este facut automat de . citirea si scrierea fisierelor in alte limbi. apoi codificarea acestora in Korean. Pentru mai multe informatii despre clasele care lucreaza cu expresii regulate.

Replace('a'. Putem folosi proprietatile Capacity si MaxCapacity pentru setarea/afisarea numarului de caractere. concatenarea sirurilor de caractere (stringuri) folosim clasa StringBuilder. Deci.AppendLine(). //apelam metoda de concatenare stringBuilder. Spre deosebire de tipul string. fiecare argument avand apelata metoda toString. va insera stringul BBB stringBuilder. urmatorul sir de caractere care va fi adaugat stringbuilder-ului va fi pe o linie noua. Capacitatea maxima este egala cu valoarea maxima a unui tip valoare int32 (int32. //inlocuim caracterul a cu caracterul z stringBuilder.Capacity). Metoda Append adauga continutul argumentelor sale. //setam numarul maxim de caractere stringBuilder. StringBuilder sb = new StringBuilder("abc". Pentru a aduce modificari continutului stringbuilder-ului. cu diferenta ca aceasta va adauga o linie noua la sfarsit. Exemplu: //creeam o instanta a clasei StringBuilder stringBuilder = new StringBuilder(). stringBuilder. . //numarul maxim de caractere care poate fi //continut de instanta curenta Console.Append("abc").Cand e nevoie de unirea.WriteLine(stringBuilder. Astfel.WriteLine(stringBuilder.MaxCapacity).Capacity = 20.MaxValue). Aceasta clasa creeaza siruri de caractere dinamice (“mutable”) – sirurile de caractere “clasice” sunt immutable. vom primi exceptie de tipul ArgumentOutOfRangeException. //dupa a patra pozite. Clasa StringBuilder are mai multi constructori. 'z'). putem construi o instanta a acesteia careia sa ii stabilim un string initial sau/si capacitatea stringbuilder-ului. O metoda asemanatoare este AppendLine. Insert. In cazul in care numarul de caractere depaseste aceasta valoare. sb va avea un string initial “abc” si nu va putea retine mai mult de 34 de caractere. Remove. tipul stringBuilder poate fi schimbat fara a fi copiat. "BBB").Insert(4. //capacitatea maxima Console. 34). se pot utiliza functiile Replace.

Text pot fi gasite pe msdn.Sort(oameni. Capture. Person p2) { return p1. care va sorta lista (array-ul) respectiv dupa varsta persoanelor. marimea absoluta a stringului si avem operatii care nu includ iteratii. mi se pare mie. liste de produse. Detalii mai multe despre spatiul de nume System.Unicode. liste de stringuri. UTF8. caruia ii putem atribui. sterge caractere/siruri de caractere. clasa StringBuilderpoate imbunatati performanta programului. Sortare pe Array De multe ori in practica stocam diverse date in array-uri. mult mai simpli. bla. Pe acestia ii vom folosi atunci cand stim dimensiunea. }). O varianta pentru clasa StringBuilder sunt vectorii de caractere.Net IComparer – se defineste un CustomComparer care implementeaza interfata IComparer. inlocui.Remove(2.Text. insa scrierea e mai scurta. }. Pentru toti membrii clasei StringBuilder. care foloseste tot un iComparer. Acum vreau sa dau o alta metoda de a face respectiva sortare. delegate(Person p1. Pe aceste date. 1). In urma cu ceva timp am scris despre asta – . putem sa il sortam scriind un comparer inline la modul urmator: Array. standarde de codificare. bla… Nu vreau sa reiau ceea ce am scris in articolul precedent aici.Age).CompareTo(p2. E mai simplu. UTF-7.Text contine clase care permit lucrul cu ASCII. Clasele care lucreaza cu expresiile regulate sunt organizate in spatiul de nume System. pastrate in array-uri avem nevoie sa executam diverse operatii.Age. Spatiul de nume System. Presupunand ca avem un array de obiecte de tip Person[] oameni = new Person[]{ …. Printre operatiile cel mai des folosite – cel putin de mine – sunt operatii de sortate. la un moment dat va trebui sa le asezam (afisam) intr-o anumita ordine. Fie ca avem liste de persoane. Match. ca si scriere decat in articolul anterior? . Clasa StringBuilder functioneaza ca un string.RegularExpressions.//eliminam de la pozitia 2 un element stringBuilder. MatchCollection. aflati mai multe detalii pe siteul Microsoft. Printre cele mai importante sunt: Regex. Folosita cu atentie.

} } public uint Age { get { return age.Format("{0} {1} . } } public override string ToString() { return string. 18). } public string FirstName { get { return firstName. "Niculescu". 15). this. new Person("Ron". "Ionescu". } } Iar in metoda Main creem un array de persoane. 22) . string lName. 22).Codul complet este urmatorul: Clasa Person este definita astfel: public class Person { private string firstName. args) Person[]{ "Popescu". 28). LastName = lName. public Person(string fName. uint age) { firstName = fName. private uint age.{2}". new Person("Pan". private string lastName. LastName. "Petrescu".age = age. il sortam si il afisam inca odata pentru a vedea efetul sortari: class Program { static void Main(string[] { Person[] oameni = new new Person("Ion". } set { age = value. "Vasilescu". new Person("Ady". } } public string LastName { get { return lastName. "Georgescu". 32). }. pe care il afisam nesortat. FirstName. } set { firstName = value. new Person("Pop". new Person("Geo". Age). } set { lastName = value.

ca scriere.22 Ionescu .32 Georgescu . p => Console. Array. Array.ForEach<Person>(oameni.ForEach<Person>(oameni.22 Ion Popescu . de afisare a elementelor array-ului: In loc de: for (int i = 0. i++) Console.22 Ady Georgescu .28 Pop Vasilescu .Length. i < oameni. Console.WriteLine(p)). }).15 Vasilescu .CompareTo(p2. Action<T> action ) .22 Dupa sortare: Geo Ionescu .18 Pan Petrescu .Length.28 Niculescu . am scris mai simplu (sau mai putin): Array. //for (int i = 0.Age).ForEach<(Of <(T>)>) primeste doi parametri: public static void ForEach<T>( T[] array.18 Petrescu . Console.32 As vrea sa subliniez modul mai simplu.Length.ForEach<Person>(oameni.15 Ron Niculescu .WriteLine(oameni[i]).Age.WriteLine(oameni[i]). i < oameni. i++) // Console.WriteLine(oameni[i]).Sort(oameni.ReadKey().WriteLine("\n\nDupa sortare:\n"). p => Console. i < oameni. Array.WriteLine(p)). Person p2) { return p1. p => Console.Array. delegate(Person p1. } } Acest cod afiseaza: Ion Geo Pop Ady Ron Pan Popescu . //for (int i = 0. i++) // Console.WriteLine(p)).

si cateva metode (proprietati) statice care permit crearea sau obtinerea unei instante a acestei structuri.Net In orice limbaj de programare si in orice program. la un moment dat este necesara folosirea datei sau timpului si diverselor operatii cu acestea. Date&Time Data si timpul in . static void Main(string[] args) { PrintDate(). desi codul este destul de bine comentat. Astazi voi scrie cateva exemple de cod care folosesc anumite operatii cu data – pe principiul ca un exemplu e mai bun decat 2 pagini de teorie!Asadar.Net exista o structura specializata care se ocupa de data si timp. namespace zeltera. Interfetele implementate de DateTime sunt: IComparable.Write("Azi este: "). mai exista si alte posibilitati de a obtine un obiect de tip DateTime: 1. pentru a usura intelegerea lui (sper ca aceasta fragmentare sa nu ingreuneze citirea!). DateTime DateTime DateTime DateTime d d d d = = = = DateTime. PrintYesterday(). Exista 12 constructori in structura DateTime.: arrayul pe care lucram si un delegate Action<(Of <(T>)>) Delegate unde specificam actiunea pe care o executam asupra fiecarui element din Array. 2. DateTime. DateTime.Now. using System. IFormattable si IConvertible. intuitiv.Today). DateTime. …si altele. In afara de aceasta cale. Console. PrintTomorrow(). 4. Toate posibilitatile de obtinere a unui obiect de tip DateTime prin folosirea contructorului sunt prezentate pe msdn aici. programul pe care l-am scris demonstreaza folosirea anumitor operatii simple cu date. Codul este impartit in mai multe metode.UtcNow. DateTime. Voi posta in continuare codul c# si apoi voi face cateva remarci pe marginea codului. Lucrul cu structura DateTime este simplu. 3. In . IComparable.Parse(dateAsString).Today. PrintDayName(DateTime. .DateTimeDemo { static class DateTimeDemo { static Random rnd = new Random().

d2 : d2 . } Console.Now.ToShortDateString().Now. TimeSpan ts = d1 > d2 ? d1 .AddDays(1). } Console.WriteLine(i GetRandomDate(). i < 25. PrintDayName(new DateTime(DateTime. 1)).ToShortDateString()).Year. // Diferenta dintre doua date DateTime d1 = GetRandomDate().WriteLine("\n---------\n").WriteLine("Diferenta dintre {0} si {1} este de {2} zile". Console. d2. ts.WriteLine("Data DateTime. d1.Days).Now. PrintDayName(new DateTime(DateTime.Year. DateTime d2 = GetRandomDate(). Random date: " + /// <summary> /// Afiseaza data de astazi /// </summary> static void PrintDate() { Console.Console.d1.ToShortDateString()).Now.Write("Ultima zi din acest an va fi ").ToString()).ToShortDateString().Write("Prima zi din an a fost ").Now.WriteLine("Data de ieri: " + DateTime. } /// <summary> /// Afiseaza data de maine /// </summary> static void PrintTomorrow() { Console. for (int i = 0. i++) { Console. } /// <summary> /// Afiseaza data de ieri /// </summary> static void PrintYesterday() { Console.ReadKey(). 1. Console.WriteLine("Astazi: " + DateTime.ToShortDateString()). 12. 31)). + ". } /// <summary> /// Afiseaza numele zilei pentru o data specifica /// </summary> /// <param name="d"></param> static void PrintDayName(DateTime d) { de ieri: " + .AddDays(1).

m. Random date: 1/1/1927 6. insa am ales sa nu folosesc aceasta varianta. } catch (Exception ex) { //exceptie apare numai in cazul in care ziua este o valoare nepermisa pentru luna //respectiva. Daca luna admite numai 30 de zile. y. continue.WriteLine(d. static DateTime GetRandomDate() { int d. 32).Year + 1). DateTime. Random date: 12/2/1911 1. Random date: 8/30/1965 4. Random date: 10/19/1972 11.Next(1900. o exceptie este aruncata. Random date: 5/24/1936 . 13).DayOfWeek. y = rnd. m = rnd. //Exista si alte posibilitati (generarea datei in functie de luna pentru care se //genereaza ziua. Random date: 7/20/1909 8. m. Random date: 12/14/1997 12. Random date: 12/13/1943 10.} Console. Random date: 9/6/1907 9. Random date: 7/14/1953 3. si numarul random generat pentru //data este 31.ToString()).Now. while (true) { try { d = rnd.Next(1. d). Random date: 7/4/2004 7. Random date: 4/19/1919 5. } } } } } Un posibil rezultat al executiei acestui program este: Astazi: 4/6/2010 10:56:27 PM Data de ieri: 4/5/2010 Data de ieri: 4/7/2010 Azi este: Tuesday Prima zi din an a fost Friday Ultima zi din acest an va fi Friday 0. return new DateTime(y.Next(1. Random date: 11/15/1935 2.

ce e aia? Sa luam un exemplu simplu: clasa String – are o serie de metode care se aplica pe sirurile de caractere. Random Random Random Random Random Random Random Random Random Random Random Random date: date: date: date: date: date: date: date: date: date: date: date: 2/28/1938 12/5/1959 2/16/1970 1/18/1984 2/14/1900 5/14/1902 2/10/1928 8/2/1909 10/11/2003 4/6/1933 8/8/2001 5/7/1966 --------Diferenta dintre 8/15/1960 si 8/21/1948 este de 4377 zile Asadar. 3. pentru a demontra folosirea metodei AddDays PrintTomorrow – afiseaza data de maine PrintDayName – afiseaza numele zilei (in engleza) al datei transmise ca argument GetRandomDate – genereaza o data aleatoare diferenta dintre doua date (exprimata in zile) – calculeaza diferenta dintre doua date si afiseaza rezultatul ca numar de zile. Pana in versiunea 2. 24. Extinderea unei clase Microsoft a introdus. imi creez o clasa de tip CommonHelperFunctions unde pun toate metodele ajutatoare etc. deocamdata despre lucrul cu data (cu timpul se lucreaza in mod asemanator). statica Now PrintYesterday – afiseaza data de ieri. Mai concret. o metoda care sa imi inverseze (reverse) un string.5 a . 21. PrintDate – afiseaza data de astazi. Daca clasa pe care o vroiam completata era declasata sealed. care sa mosteneasca clasa pe care vrem sa o extindem. 18. Sau… extind clasa String adaugandu-i o metoda noua: Reverse(). 5.13. Aici se poate vedea si folosirea compararii a doua date: TimeSpan ts = d1 > d2 ? d1 – d2 : d2 – d1. derivata din clasa pe care vrem sa o extindem.0. Instanta DateTime este obtinuta folosing proprietatea 2. derivarea ei nu este posibila. 16. 15. 17. 19. am scris o serie de metode care executa tascuri simple: 1. Intr-unul din articolele urmatoare voi vorbi despre foramtarea pentru afisare a unei instante a DateTime. de exemplu.Net framework posibilitatea de a extinde o clasa fara a creea o noua clasa. Extinderea rezolva problema claselor declarate sealed – orice clasa accepta extinderi. 20. in versiunea 3. 14. 6. 23. Printre metodele pe care le pot folosi nu se gaseste insa. scriu codul de inversare inline (e mic… 2 linii. doar). Am mai multe posibilitati: scriu o metoda in locul unde am nevoie care sa faca asta. Cam atat. pentur a introduce (adauga) noi metode unei clase singura posibilitate era crearea unei noi clase. . 4. 22.

IsDouble. IsDate. am ales sa extind clasa String adaugandu-i urmatoarele metode: Reverse. CountWords. CountNonEmptyChars. AlternateCase. i >= 0. else false</returns> public static bool IsDate(this String str) { try { DateTime.Pentru a exemplifica mai bine. i--) rev. return rev. } catch { return false.ToString(). StringBuilder rev = new StringBuilder(). else . Numele metodelor pe care vreau sa le introduc spun (in engleza. statica. return true.1. /// <summary> /// Reverse the string /// </summary> /// <param name="str">string to reverse</param> /// <returns>reversed string</returns> public static String Reverse(this String str) { if (str == null) return null.Append(str[i])..Parse(str).:/<>(){}[]\"'= \n\r\t". for (int i = str.Length . } <summary> Check is a string represent a valid date </summary> <param name="str">string to check</param> /// <returns>true if the string represent a valid date.?!. } } <summary> Check if the string is a valid number (integer) </summary> <param name="str">string to check</param> /// <returns>true if the string represent false</returns> public static bool IsInteger(this String str) { /// /// /// /// /// /// /// /// a integer. ce-i drept) cam ce face respectiva metoda. In continuare voi lista codul care implementeaza cele 7 metode propuse: public static class StringExtensions { private static string separators = ". Pentru a implementa ceea ce am propus mai sus se procedeaza in felul urmator: se creeaza o clasa publica. in care se definesc metodele repsective ca metode statice si care accepta ca prim parametru ceva de genul urmator: this string str. IsInteger.

Split(separators.try { int. for (int i = 0. } /// <summary> /// Count the words on a given string /// </summary> /// <param name="str">a phrase (string)</param> /// <returns>number of words</returns> public static int CountWords(this string str) { return str. return true.RemoveEmptyEntries).IsWhiteSpace(str[i])) continue. counter++. return true. StringSplitOptions.ToCharArray(). } catch { return false. } return counter. i++) { if (Char. } catch { return false.Parse(str). else /// <summary> /// Counts all the not empty chars on the given string /// </summary> /// <param name="str">string to count</param> /// <returns>the number of non empty chars found</returns> public static int CountNonEmptyChars(this string str) { int counter = 0. i < str.Parse(str). } } a double. } .Length.Length. } } /// /// /// /// <summary> Check if the string is a valid number (double) </summary> <param name="str">string to check</param> /// <returns>true if the string represent false</returns> public static bool IsDouble(this String str) { try { double.

Odata inclus numele de spatiu in proiectul curent. bool startsWithUpper) { if (str == null) return null. StringBuilder alt = new StringBuilder(). aceste metode vor fi vizibile si in intelisense-ul visual studio (cam asa): .Length. upc = !upc. else alt.ToLower(str[i])). i < str. pentur orice obiect de tip string vom avea disponibile toate cele 7 metode definite. de fiecare data cand vrem ca aceste metode sa fie disponibile pentur a fi folosite cu clasa String.ToUpper(str[i])). trnuie doar sa folosim o instructiune using care sa importe numele de spatiu unde am definit clasa StringExtensions. i++) { if (upc) alt. } return alt. for (int i = 0.Append(Char.<summary> Transforms a string by alternating the letters case </summary> <param name="str">string to transform</param> /// <param name="startsWithUpper">build the transformed string starting with a uppercase char</param> /// <returns> the transformed string</returns> public static string AlternateCase(this string str. In plus.ToString().Append(Char. bool upc = startsWithUpper. } } /// /// /// /// Acum.

WriteLine(testString. Q: Merge pe Visual studio 2005 sau 2003? A: Nu. Q: Cum pot totusi folosi extensiile daca nu am Visual Studio mai nou de 2005? A: Instaleaza unul. 4. Codul folosit in exemplu e doar pentru a demostra extinderea unei clase si nu a fost optimizat/verificat. } } de nevide: cuvinte: {0}". Console.WriteLine("Caractere testString.WriteLine("Numar testString.WriteLine("Alternate case:"). {0}". Console. Q: E codul prezentat optim? A: Nu stiu.WriteLine(testString.CountWords()). Console.Reverse()).CountNonEmptyChars()). 3. Console. care are ca rezultat: Reverse: god yzal eht revo spmuj xof nworb kciuq ehT Caractere nevide: 35 Numar de cuvinte: 9 Alternate case: ThE QuIcK BrOwN FoX JuMpS OvEr tHe lAzY DoG FAQ: 1. Console.WriteLine("Reverse:"). Q: Am o idee de extindere/imbunatatire a exemplului prezentat. (din cate stiu eu). Daca exemplul e relevant. il includ in articol. Console. Ce fac? A: Scrii un comentariu.O sa inchei cu un exemplu care exemplifica folosirea a tot ce am scris mai sus: class Program { static void Main(string[] args) { string testString = "The quick brown fox jumps over the lazy dog".AlternateCase(true)). 2.ReadKey(). Console. Microsoft ofera versiuni express ale ultimului Visual Studio (gratis). Clasa Process .

ProcessStartInfo(“http://google.. cod care. Astazi o sa fac o scurta prezentare a acestei clase. //. un proces poate fi controlat in diverse feluri.. cod static { Process p.StartInfo = new ProcessStartInfo("notepad.. Daca lucram in . urmand ca in viitor sa revin cu mai multe detalii si mai multe exemple. cod static void Main(string[] args) { Process p = new Process(). evident. asa cum ai ghicit. Codul devine: //…. Ce putem face. simplu. un notepad! La ce ne trebuie? Deocamdata nu ne trebuie. relativa..Start().. Nume aplicatiei poate fi inlocuit cu… un url. //. Sa pornim..Net asta se face cu ajutorul clasei Process aflata in namespace-ul System.Start().. } //. p. de exemplu. p. numele executabilului daca el este definit prin nu stiu ce variabile de system).Diagnostics.. Insa nu e singura posibilitate.exe se poate inlocui cu orice alt executabil (cale absoluta. cod void p = = new Main(string[] args) new Process().StartInfo p. cod Codul de mai sus. Asta se face cu ajutorul metodei Kill() asociata obiectului: using System. } //…. Un mod de a controla un process este sa il opresti.Sunt situatii in care din aplicatia pe care o scriem avem nevoie sa pornim o alta aplicatie.. . e doar un exemplu: using System. cu ajutorul acestei clase.exe").Diagnostics.com/”). Odata pornit. notepad.Diagnostics. deschide o sesiune de notepad. va deschide browserul default al sistemului si va incarca pagina specificata (google in cazul asta).

.Start()..UseShellExecute = false.CreateNoWindow = false.EndOfStream) { Console.RedirectStandardOutput = true.WriteLine(p. //citeste linie cu linie //Console. //Console.StandardOutput.WriteLine(p.Sleep(2000). p.StartInfo = psi..exe"). p.StartInfo = new ProcessStartInfo("notepad..Kill().WriteLine()..WriteLine("Exit code: {0}". p.ReadLine()). cod //asteapta 5 secunde Asa cum se observa..ConvertFromUtf32(p.nu trebuie executat in block while. //. Cred ca destul de utila este pornirea unui proces care reprezinta o aplicatie de tip consola.StandardOutput. //trebuie setata false pt a putea redirecta StandardOutput p. } Console. p. prin faptul ca din consola se primesc date (output-ul consolei) sau. Aceasta difera un pic de procesele de tip fereastra.ExitCode). cod static void Main(string[] args) { Process p = new Process(). ProcessStartInfo psi = new ProcessStartInfo(externalConsoleApp).StandardOutput.. se transmit date.. Console. obiectul de tip Process are o proprietate p.Write(Char. eventual.ReadKey().StandardOutput. //nu vreau sa fie creata fereastra aplicatiei psi. while (!p. //calea spre aplicatia console psi. Thread. Console.. } //.ReadToEnd()). //citeste tot out-put-ul ca bloc .Diagnostics. //vreau sa redirectez StandardOutput pt a-l putea citi psi. } //.Start().static void Main(string[] args) { Process p = new Process().Read())). Pentru a executa si primi output-ul unei aplicatii de tip consola se procedeaza asa: using System. p.StartInfo de tip ProcessStartInfo unde se definesc practic parametrii procesului care va fi pornit. cod .

consola. Daca fisierul e hidden (-h). O alta operatie pe care o putem face prin intermediul programului notepad e sa tiparim un fisier text.. metoda Main are un argument: string[] args. unde [lista de parametri] reprezinta o lista optionala de parametri transmisi programului numeProgram. sau treci mai departe. care reprezinta exact ceea ce utilizatorul va trimite ca parametru/i programului nostru. Cei care au folosit sisteme de operare MS_DOS sau unix/linux stiu cel mai bine cat de util este ca un program sa poata fi executat cu o lista de parametri si sa nu trebuiasca sa interactionam cu el pe parcursul executiei. muta fara sa intrebi. Sunt cazuri cand vreau sa nu fiu intrebat. Pentru a face asta. Cum functioneaza asta? Simplu: windowsul executa. nu il muta. unde fullPath_fisier. gasim fisierul care ne intereseaza si cu un simplu dublu click fisierul respectiv este deschis in notepad. Un exemplu mai bun decat cel prezentat anterior este batranul notepad. Cand vrem sa vedem un fisier text.txt.exe. Sa presupunem ca am un program care muta fisierele din directorul Images in directorul Pictures. executia unui program incepe in metoda Main.exe /P fullPath_fisier. Scopul articolului de astazi e sa construiesc o aplicatie simpla. pornim Windows Explorer.exe. Cand programul intalneste un fisier care este ReadOnly sau Hidden ar trebui sa ceara confirmarea (asa cum Windows Explorer face) pentru a muta fisierul. o comanda de genul: notepad. Vreau sa pot sa ii spun de la inceput: nu ma intreba.exe -ro yes -h no. Voi construi o aplicatie consola pentru a simplifica exemplele oferite. mutal.. Asta arata cam asa: numeProgram. insa orice executabil (consola. asta ar suna cam asa: daca fisierul care trebuyie mutat e ReadOnly (-ro). Aceasta metoda arata cam asa: static void Main(string[] args) { //.Argumente in linia de comanda Marea majoritate a programelor pe care le folosim accepta la executie o serie de parametri.exe fullPath_fisier. .txt este parametru trimis aplicatiei notepad. daca exista ceva ReadOnly.exe [lista de parametri]. Array-ul va fi creat prin ruperea string-ului trimis ca parametru acolo unde apar spatiile albe (space). ne folosim de un alt argument: notepad. Tradus. Cum as vrea sa pot scrie asta? Cam asa: muta. fereastra) poate primi argumente. in fundal. Asa cum probabil stiti. care sa accepte o lista de parametri.txt. aplicatia porneste } Dupa cum se poate vedea.

este suficient sa facem urmatoarea verificare: if(args. un fel de hello world. Foarte multe aplicatii accepta parametri transmisi in linia de comanda. in practica. } Console. care sa primeasca ceva parametri si sa si faca ceva cu ei. } } } else { Console.Length..exe ar treebui sa aiba ceva de genul: bool askForReadOnly = true. if(args. Daca userul nu specifica altceva in linia de comanda. lName).avem ceva parametri for(int i=0. string lname ="". static void Main(string[] args) { string fName = "". return. de exemplu.Length) avem cava dupa -fn { fName = args[i+1]. atunci aceste valori ar trebui folosite.Length > 0) { //. bool askForHidden = true. intern.avem ceva parametri } Hai sa creem un program simplu.Length > 0) { //.Length) avem cava dupa -ln { lName = args[i+1]. In viata reala. in cazul exemplului dat la inceput..WriteLine("Lipsesc parametrii"). } if(args[i] == "-ln" && i + 1 < args. Ceea ce ar trebui sa faca parametri trimisi programului este sa modifici niste valori prestabilite.WriteLine("Salut {0} {1}".Pentru a verifica daca am primit sau nu parametri. } //verificam daca //verificam daca In exemplul prezentat nu fac verificari in ceea ce priveste corectitudinea parametrilor. insa sunt si foarte mult . Pot exista situatii in care sunt folosite niste valori prestabilite iar prin parametri primiti de la utilizatori doar modificam aceste valori.. i++) { if(args[i] == "-fn" && i + 1 < args. cu programul care muta fisiere dintr-un folder in altul. fName. Utilizatorul poate executa urmatoarea linie: muta.. i<args. verificarile trebuiesc facute. Probabil.exe -ro yes -h no. programul muta.

programatori, sau companii, care nu insclud optiunea de a transmite acest tip de parametri. Poate data viitoare cand scrii o aplicatie te gandesti: ce ar fi daca in loc sa pot deschide un fisier word cu dubluclick din windows explorer ar trebui sa deschid Word, sa apas Open, sa caut locul unde e fisierul pe care vreau sa il deschis etc. Am scris acest articol mai mult pentru a aminti programatorilor de aceasta posibilitate si mai putin pentru a da exemple bune de folosire.
DEBUG

Una dintre cele mai importante facilitati pe care o ofera Visual Studio este cea de Debug. Ce inseamna asta? A face Debug inseamna a analiza ce se intampla, la executie, in interiorul aplicatiei asupra careia facem Debug. Aceasta operatie are ca scop gasirea si repararea erorilor (bugs) dintr-o aplicatie. Aceasta operatie se face cu ajutorul uor instrumente speciale, numite debuggers. Cu ajutorul acestor unelte se poate vedea la runtime ce se intampla in timpul executiei aplicatiei asupra careia se face operatia de debug. In cazul Visual Studio uneltele sunt incluse in pachetul Visual Studio, userul netrebuind sa instaleze separat nimic. Exista, din cate stiu eu, doua metode de a porni o operatie de debug: prin apasarea butonului Start Debuging din toolbar-ul Standard (sau comanda din meniul Debug) sau, metoda a doua, prin atasarea de o aplicatie care ruleaza, folosind comanda Attach to Process, din acelasi meniu. Vezi in imaginile urmatoare cele doua optiuni. O captura de ecran pentru butonul debug:

si

o

captura

de

ecran

pentru

meniul

Debug:

O sa explic cum se folosesc fiecare dintre aceste optiuni. O sa scriu un program scurt, caruia o sa ii fac Debug. Acest program, simplu, care contine, deocamdata, numai metoda Main, este urmatorul:
class Program { static void Main(string[] args) { Console.Write("Name: "); string str = Console.ReadLine(); for (int i = 0; i < 5; i++) { Console.WriteLine(i + ". Hello " + str); } } }

Tot ce face acest program e sa citeasca de la tastatura un string si sa afiseze de 5 ori mesajul Hello plus stringul citit de la tastatura, iar in fata fiecarui rand afisat apare si numarul itinetatiei. La executie vedem ceva de genul:
Ady 0. Hello Ady 1. Hello Ady 2. Hello Ady

3. Hello Ady 4. Hello Ady

Pentru a Opri executia programului la un moment dat, avem nevoie de un BreakPoint. Un BreakPoint este un punct in cod unde debuggerul opreste temporar executia programului si permite examinarea starii lui in momentul respectiv. Pentru a stabili un astfel de punct (loc) ceea ce trebuie facut e sa clickam in editor, in Visual Studio, in marginea stanga a ferestrei in care editam codul, in dreptul liniei unde vrem sa stabilim acel BreakPoint. In programul exemplu eu am stabilit 2 astfel de locuri:

Se observa ca linia unde executia programului va fi intrerupta este colorata diferit.

Asta inseamna ca programul este oprit in puctul respectiv.Apasam butonul Debug (sau tasta F5) pentru a porni operatia de Debug: In imaginea anterioara se observa cum linia unde a setat primul breakPoint este evidentiata diferit. Pentru a continua. Scriu in . cu galben. Eu apas acum F5. tasta F10 pentru a continua executia prin executarea urmatoareil linii de program (numai o linie) sau F11 pentru a continua executia prin salt in interiorul functiei care se executa in linia in care am oprit – numai in cazul in care suntem intr-o linie in care se executa cod definit intr-o alta metoda – nu e cazul actual. e nevoie sa ii spunem Debugger-ului sa mearga mai departe – apasam tasta F5 pentru a continua executia programului. Programul isi continua executia si eu trebuie sa introduc un nume.

apasand tasta F10. respectiv numele introdus de mine in fereastra Consola: Daca versiunea de Visual Studio este Profesional. Insa despre asta intr-un alt articol. voi vedea valoarea ei. Daca pozitionez cursorul mouse-ului deasupra numelui unui obiect. Acum urmaresc valorile variabilei i in interioru ciclului for: Continui asa. Observ ca la fiecare apasare a tastei respective executia avanseaza. In momentul in care aplicatia a ajuns in puctul in care ne cere sa introducem numele. revenim la visual studio si din meniul . A doua metoda de a intra in modul debug este prin atasarea la un proces care ruleaza. in sensul ca pot vedea starea obiectelor care imi compun aplicatia. Continui executia programului. Pornim aplicatia (apasam Ctrl+ F5. In fereastra codului. Programul isi continua executia pana la urmatorul breakPoint unde debugger-ul preia controlul. in momentul in care sunt in Debug Mode am acces la memoria aplicatiei. de data asta linie cu linie. pana cand programul isi termina executia. iar linia care se executa in momentul curent este evidentiata. Pozitionand cursorul mouse-ului deasupra variabilel str. Visual Studio imi va afisa valoarea respectivei valori asa cum este ea in momentul respectiv in memorie. la runtime.fereastra consola un nume: “Ady” si apas enter. sau executam din folderul \HelloWorld\HelloWorld\bin\Debug\HelloWorld.exe aplicatia. valoarea variabilelor se poate medifica in fereastra debug. adica start without debugging.

descris mai sus. Din acest moment procesul de debug continua ca si in primul caz.Debug apelam Attach to process: In acest moment avem o fereastra care contine numele proceselor care sunt executate in calculator: Selectam procesul care are numele identic cu numele aplicatiei noastre si apasam butonul Attach. Programul .

opreste la ficare BreakPoint. In momentul in care Visual studio este in mod Debug. poate fi executat linie cu linie. click cu butonul din dreapta deschide un meniu care are cateva comenzi importante. dintre care vreau sa evidentiez doua: Run To Cursor . se pot modifica valorile variabilelor (Pro) etc.

Run To Cursor este utila in cazul in care vrem sa continuam executia programului pana intr-un anumit punct. punct in care sa fie iarasi intrerupta executia.si Set next Statement: Ce sunt cele doua comenzi? Prima. Putem sa punem acolo un breakPoint nou. sau putem sa pozitionam cursorul in editor in locul .

Cu ajutorul acesti comenzi se continua executia programului de la un punct dorit de programator – inainte sau dupa punctul curent. pareri si sugestii. Acesta este un prim articol despre operatia de debug. . Multumesc si astept comentarii. Vor mai fi si altle.respectiv si sa apelam comanda Run To Cursor. pentru a relua executia unui bloc etc. A doua comanda este Set next Statement. La ce foloseste asta? Pentru a evita o eroare (care trebuie corectata ulterior).

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->