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.

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

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

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

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

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

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

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

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

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

. while(true) { // .Un alt mod de a declara o variabila de acest tip este: int? a = null. Sintaxa generala este: for (int i = 0. ca in exemplul urmator: int i = 0. Le voi analiza pe rand. } //intrerupe ciclul O alta modalitate de a scrie un bloc ce se repeta la infinit este cu ajutorul keyword-ului while: int i = 0. } care este un ciclu infinit. ) { // . .. if(i++ == 5) break. Tipuri repetitive In limbajul c# exista mai multe posibilitati de a executa in mod repetat anumite blocuri de cod (ciclu). iar verificarea se poate face in felul urmator: Console. ) { // . Acest bloc de cod ar trebui intrerupt (printr-o intructiune break.. a ?? “null”). if(i++ == 5) break. exemplificand utilizarea lor. Cel mai simplu ciclu este ciclul for.. i <= 5. //intrerupe ciclul .WriteLine(“valoarea variabilei este {0}”. for (. i++) { //executa ceva de 5 ori } O alta modalitate de scriere a unui bloc for este urmatoarea: for (.. 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. ..

2 * n). De exemplu: int x = int. 9. 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>). foreach (int n in numbers) { Console. 8. 3.WriteLine(x++). Am lasat la final foreach. n. 6. Instructiunile do…while sunt o alta metoda de a executa inmod repetat anumite linii de cod: int x = 0. do { Console. } Daca userul introduce un numar multiplu de 5. insa putin diferit de modurile cum lucreaza blocurile descrise anteorior. 5.WriteLine(x). deoarece este o metoda de a executa in mod repetitiv anumite operatii. 10 }. Exemplu folosind un array: int[] numbers = new int { 1.Parse(Console. } Acest exemplu va afisa perechi de tipul n -> 2n pentru fiecare numar din array-ul de int folosit. 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.NET .WriteLine("{1} -> {2}". Conversia datelor in . 4. codul blocului while nu se executa nici macar o data. while (x % 5 != 0) { Console. 2. x++. } while (x < 5).ReadLine()). 7. Codul dintr-un ciclu while poate sa nu fie executat niciodata.} Acest bloc de cod este echivalent (functional) cu cel anterior (folosinf for).

Exista doua tipuri de conversii numerice : Conversii implicite .Inainte de a continua prezentarea tipurilor de date din C#. O conversie permite ca o expresie de un anumit tip. cunoastem structura tipurilor de date astfel : Definim expresie in modul urmator : O expresie este o combinatie valida de operatori. literali si variabile. Deocamda. 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.

Tipul float este suficient de cuprinzator pentru a memora orice valoare de tip int(conversie prin largire ). invers nu se poate efectua automat. i = 10. Chiar daca se poate efectua conversia automata din int in float. float f. Daca sunt indeplinite cele doua conditii. //conversia automata nu are loc i = f.4F. float f. f = 30. atunci valoarea din partea din dreapta este convertita la tipul din partea stanga.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. An explicit conversion exists (are you missing a cast?)“ Conversii explicite . int i. i = 10. int i. 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.

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

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

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

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

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

inclusiv secvente escape (reprezentarea caracterelor care nu au reprezentare grafica si a celor speciale). Pentru concatenarea (unirea) sirurilor de caractere se mai foloseste operatorul “+”. la registri.Text. 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. In C#. tablourile pot avea mai multe dimensiuni. . Despre ARRAYS Un tablou reprezinta o colectie de variabile de acelasi tip. Tipul acesta de sir incepe cu “@” inainte ghilimelor. Un exemplu complet in articolul despre clasa System. la prelucrarea lor. 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. string cale = @"c:\TipReferinta\string.Accesul se face printr-o variabila referinta.cs". “verbatim” – se folosesc cand se fac referiri la fisiere. fapt care conduce la colectarea automata a spatiului ocupat de tablourile neutilizate.regulate – contine intre ghilimele zero sau mai multe caractere. aici. referite prin intermediul unui nume comun. string sir = "Limbajul C# este accesibil!". tablourile sunt implementate ca obiecte. Exemplu : string sirConcatenat = "Limbajul " + "C#" + " " + "este accesibil". este ca. Diferenta dintre tablourile din alte limbaje si cele din C#.

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

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

WriteLine("Elemente colectia1:"). foreach (int numar2 in colectie2) { Console. } Console. 23.WriteLine("Elemente colectia2 :"). Console. 23. 4. } Tablourile multidimensionale Tablourile multidimensionale au doua sau mai multe dimensiuni. } //colectie2 refera pe colectie1 colectie2 = colectie1. Cand incercam sa atribuim o valoare de tipul referinta la un tablou al unei altei valori de tip referinta ( copiere ).Console.WriteLine(numar). //dimensiune 2X2 int [.2].WriteLine("Elemente colectia1:"). Console. int[] colectie2 = { 23. 23 }.] matrice = new int[2. } Console.WriteLine(numar2).WriteLine(numar2). int[] colectie1 = { 4.WriteLine("Numarul listaNume. 5 }. 5.Length). Cele mai simple tablouri multidimensionale regulate sunt cele bidimensionale. 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. Console. se modifica doar obiectul referit de catre acea variabila. In cadrul acestui tablou. foreach (int numar in colectie1) { 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.WriteLine(numar). de elemente din vector este {0}".WriteLine("Dupa atribuire :"). pozitia unui anumit element este data de doi indici.WriteLine("Elemente colectia2 :").

Despre operatori Un operator este un simbol care indica o actiune. Operandul este valoarea asupra careia se executa operatia.//atribuim valoare elementului de pe linia 2 si coloana 1 matrice[1. //Scadere Semnificatie Adunare ( si plus unar ) Scadere ( si minus unar ) Inmultire Impartire Impartire Modulo ( rest ) Incrementare Decrementare . Clasificarea operatorilor Operatorii sunt impartiti 3 categorii. operatorul conditional. Operatori unari – actioneaza asupra unui singur operand. exista urmatorii operatori aritmetici : Operator + * / % ++ – Exemplu : int numar = 5. Operatorii alaturi de operanzi formeaza o expresie.WriteLine(numar + numar2). Operatori ternari – actioneaza asupra a trei operanzi. Exista doar unul de acest tip.0] = 230. 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. int numar2 = 13. //Adunare Console. Operatorii aritmetici In C#. Operatori binari – actioneaza intre doi operanzi.

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

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

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

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

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

WriteLine("Apelul functiei Afiseaza din clasa derivata"). 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. Nu se pot suprascrie metodele care nu sunt virtuale. metodele nu sunt virtuale. Implicit. 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. } } . //instantiem pe un obiect din clasa derivata Baza obiect1 = obiect2. //afiseaza functia din clasa de Baza obiect1. Modificatorii virtual si override Virtual este folosit in declararea unei metode sau a unei proprietati. Implementarea unui membru virtual poate fi schimbata prin suprascrierea membrului intr-o clasa derivata. Acestea se vor numi membri virtuali.WriteLine("Apelul functiei Afiseaza din clasa de baza\n").Afiseaza(). Exemplu: class Baza { public virtual void Afiseaza() { Console.Afiseaza(). pe baza tipului declarat al obiectelor : Derivata obiect2 = new Derivata(). obiect2. } } class Derivata : Baza { public void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n").Exemplu: class Baza { public void Afiseaza() { Console.

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

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 . private int varsta. ea ar primit implicit tot acest modificator de acces. //declarea unei metode //care va returna true/false public bool Admis() { // } } Datorita modificatorului de acces public.Net accesibil oricarui membru al clasei care-l contine si al claselor derivate implicit. 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. In cazul in care nu adaugam un modificator in declarea clasei.public class Student { //declararea variabilelor membru public double nota. clasa Student va fi vizibila peste tot si cu acces nelimitat.

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

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

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

//clasa de baza class Forma { //membri variabila protected double _inaltime. 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. } } Constructorul clasei Dreptunghi initializeaza si membrii mosteniti de la clasa Forma impreuna cu campul propriu stil. } In acest caz. protected double _latime. //constructor pentru clasa Forma public Forma(double inaltime. double inaltime. class A { public int a. double latime) : base(inaltime. la compilare va aparea mesajul : . } } //clasa Dreptunghi mosteneste //clasa Forma class Dreptunghi : Forma { //membru variabila privat string stil. _latime = latime. double latime) { _inaltime = inaltime.obiectului care apartine de clasa de baza. latime) { stil = s. //utilizam base pentru //a executa constructorul //clasei de vaza public Dreptunghi(string s. } class B : A { int a.

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

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

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

Sintaxa este comuna cu cea folosita la mostenirea claselelor.#region I1 Members public void Metoda1() { throw new NotImplementedException(). numele acestora vor fi separate prin “. Daca o clasa mostenteste o interfata care mosteneste o alta interfata. 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. } public void Metoda4() { throw new NotImplementedException(). } #endregion } In cazul in care o clasa implementeaza mai multe interfete. } //clasa Test va trebui sa implementeze toate mteodele din A si B . Exemplu : //interfata accesibila in tot programul public interface A { void Metoda1(). Mostenirea interfetelor O interfata poate mosteni o alta interfata. } #endregion #region I2 Members public void Metoda3() { throw new NotImplementedException(). void Metoda2(). } public void Metoda2() { throw new NotImplementedException(). } //interfata B va include metoda1 si metoda2 plus metoda3 public interface B : A { void Metoda3().”. clasa va trebui sa contina implementari pentru toti membri definiti pe lantul de mostenire al interfetei.

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

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

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

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

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).

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

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

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

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

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

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

rar ListaVectori. Conceptul de generics a aparut in versiunea 2. Vom rezolva problema convertind la tipul Cont.WriteLine(c. Impreuna cu alte colectii din . o colectie tipizata. 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. C# este un limbaj type-safe. si nu la executie (run-time).Cont’. . An explicit conversion exists (are you missing a cast?)”. An explicit conversion exists (are you missing a cast?) Motivul este ca ArrayList este o lista de Objects. 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. de tipul: “Cannot implicitly convert type ‘object’ to ‘ContExemplu. altfel primeam eroare la compilare. in sensul ca mare parte dintre errorile datorate tipurilor de date folosite sunt detectate la compilare). Am expus aceasta problema. O lista cu membrii ArrayList se gaseste pe msdn. in plus avand avantajul de typesafe. Foarte asemanatoare cu ArrayList este clasa List. Vom scrie despre aceasta clasa in articolul viitor.Cont’.Exista si StringCollection.Sold(). doar ca implementarea si regulile de utilizare difera in . lucru care permite ca unele eventualele erori sa fie returnate la compilare (acest lucru face ca programul sa fie stabil. Notiunea de cod generic poate parea cunoscuta celor care programeaza in C++.Cont c = conturi[0]. Cannot implicitly convert type ‘object’ to ‘ContExemplu. Codul folosit in exemplele anterioare: • • ContExemplu. c. Console.0 a limbajului C#.Net care sunt strongly typed.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.Net. pentru a intelege mai bine termenul de generic. //facem conversie la Cont Cont c = (Cont)conturi[0].Sold()).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

daca pentru un bloc se date dat calculam valoarea hash. Eu.. O functie hash are (ar trebui sa aiba) urmatoarea proprietate: este imposibil de gasit. Mai important decat masurarea duratei unei operatii este insa masurarea diferentei de timp intre executarea codului o data si de 100 de ori. Este imposibila reconstituirea satelor care au generau o anumita valoare hash. 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. O functie Hash nu este inversabila...WriteLine("Executia a durat: " + stopWatch. La fel si pentru webservice. am folosit ceva asemanator pentru a verifica timpul necesar unei aplicatii care imi genereaza documente pdf online pentru un document. prin calcule. un alt bloc de date care sa aiba aceeasi valoare hash. informatii care ajung in logurile aplicatiei. sa generez un grafic imi ia 80 milisecunde... E important sa stii. Informatiile obtinute despre timpul de executie al anumitor portiuni – blocuri – de cod sunt. Valoarea hash a doua blocuri de date ar trebui sa fie identica daca cele doua blocuri de date sunt identice.. daca iti ia 1 secunda sa citesti ceva din baza de date sau daca iti ia o milisecunda. Utilitatea acestui tip de masuratoare depinde de la aplicatie la aplicatie. cand scrii o aplicatie. in practica. . 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.Console. Daca scriu loguri. de obicei de dimensiune fixa. Sau cu alte cuvinte. in cazul meu cel putin. Valoarea hash are o lungime fixa indiferent de lungimea datelor pentru care a fist calculata. Modificari minore in blocul de date duce la aparitia de modificari nepredictibile si importante in valoarea hash calculata. este imposibila gasirea prin intermediul unui calcul a unui alt bloc a carui valoare hash sa fie aceeasi. Functiile hash sunt folosite in semnaturi digitale sau pentru verificarea integritatii datelor. Cu alte cuvinte. 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.Text. atunci scriu si informatii despre timpul de executie.ElapsedMilliseconds + "milisecunde") //. In articolul urmator vom discuta despre spatiul de nume System. care depinde de tipul algoritmului folosit si nu de cantitatea (lungimea) datelor de intrare.

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

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

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

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

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

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

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

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

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

insa am ales sa nu folosesc aceasta varianta. d). continue.Next(1.ToString()). static DateTime GetRandomDate() { int d. Random date: 12/14/1997 12. m.Next(1900. //Exista si alte posibilitati (generarea datei in functie de luna pentru care se //genereaza ziua.Year + 1). Random date: 1/1/1927 6.WriteLine(d. return new DateTime(y. Daca luna admite numai 30 de zile. Random date: 7/4/2004 7. o exceptie este aruncata. Random date: 8/30/1965 4.DayOfWeek. m. Random date: 10/19/1972 11.Next(1. y. Random date: 9/6/1907 9. Random date: 12/13/1943 10. DateTime. m = rnd. 13).Now. Random date: 7/14/1953 3. y = rnd. Random date: 5/24/1936 . Random date: 11/15/1935 2. Random date: 12/2/1911 1. Random date: 4/19/1919 5.} Console. Random date: 7/20/1909 8. } } } } } 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. 32). while (true) { try { d = rnd. } catch (Exception ex) { //exceptie apare numai in cazul in care ziua este o valoare nepermisa pentru luna //respectiva. si numarul random generat pentru //data este 31.

Pana in versiunea 2. Printre metodele pe care le pot folosi nu se gaseste insa. 19. 16. Am mai multe posibilitati: scriu o metoda in locul unde am nevoie care sa faca asta. 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. am scris o serie de metode care executa tascuri simple: 1. in versiunea 3. care sa mosteneasca clasa pe care vrem sa o extindem. 21. Mai concret. 22. Aici se poate vedea si folosirea compararii a doua date: TimeSpan ts = d1 > d2 ? d1 – d2 : d2 – d1. o metoda care sa imi inverseze (reverse) un string. Instanta DateTime este obtinuta folosing proprietatea 2. 20. Cam atat. . de exemplu. 14.0. 5. Intr-unul din articolele urmatoare voi vorbi despre foramtarea pentru afisare a unei instante a DateTime. 3. ce e aia? Sa luam un exemplu simplu: clasa String – are o serie de metode care se aplica pe sirurile de caractere. deocamdata despre lucrul cu data (cu timpul se lucreaza in mod asemanator). 4. 6. 18. 17. statica Now PrintYesterday – afiseaza data de ieri. doar). Extinderea unei clase Microsoft a introdus.5 a .13. Extinderea rezolva problema claselor declarate sealed – orice clasa accepta extinderi. Daca clasa pe care o vroiam completata era declasata sealed. Sau… extind clasa String adaugandu-i o metoda noua: Reverse().Net framework posibilitatea de a extinde o clasa fara a creea o noua clasa. 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. 23. PrintDate – afiseaza data de astazi. 24. derivarea ei nu este posibila. scriu codul de inversare inline (e mic… 2 linii. derivata din clasa pe care vrem sa o extindem. 15. imi creez o clasa de tip CommonHelperFunctions unde pun toate metodele ajutatoare etc. pentur a introduce (adauga) noi metode unei clase singura posibilitate era crearea unei noi clase.

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

return true. } /// <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. i++) { if (Char. } catch { return false.RemoveEmptyEntries). counter++.Split(separators.try { int. 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.ToCharArray(). } . } catch { return false. } } /// /// /// /// <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.Length. i < str.Parse(str). for (int i = 0.Length. StringSplitOptions.Parse(str). return true. } } a double. } return counter.IsWhiteSpace(str[i])) continue.

trnuie doar sa folosim o instructiune using care sa importe numele de spatiu unde am definit clasa StringExtensions. aceste metode vor fi vizibile si in intelisense-ul visual studio (cam asa): . else alt.Append(Char. In plus. de fiecare data cand vrem ca aceste metode sa fie disponibile pentur a fi folosite cu clasa String.Length. } } /// /// /// /// Acum.ToString(). bool startsWithUpper) { if (str == null) return null. bool upc = startsWithUpper. upc = !upc. } return alt.Append(Char. StringBuilder alt = new StringBuilder(). for (int i = 0.<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.ToLower(str[i])). pentur orice obiect de tip string vom avea disponibile toate cele 7 metode definite. i++) { if (upc) alt. i < str.ToUpper(str[i])). Odata inclus numele de spatiu in proiectul curent.

Q: Am o idee de extindere/imbunatatire a exemplului prezentat. Daca exemplul e relevant.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".CountWords()). Console. {0}".ReadKey(). Q: Merge pe Visual studio 2005 sau 2003? A: Nu.WriteLine("Numar testString.WriteLine("Reverse:").WriteLine("Alternate case:"). Console. } } de nevide: cuvinte: {0}".CountNonEmptyChars()). Console.Reverse()). 2. il includ in articol. 3. 4.WriteLine("Caractere testString. Console. (din cate stiu eu). Console. Ce fac? A: Scrii un comentariu. Q: E codul prezentat optim? A: Nu stiu. Codul folosit in exemplu e doar pentru a demostra extinderea unei clase si nu a fost optimizat/verificat.AlternateCase(true)). Q: Cum pot totusi folosi extensiile daca nu am Visual Studio mai nou de 2005? A: Instaleaza unul. 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. Microsoft ofera versiuni express ale ultimului Visual Studio (gratis). Clasa Process .WriteLine(testString.WriteLine(testString. Console. Console.

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

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

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

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

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.

Programul isi continua executia si eu trebuie sa introduc un nume. 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. Pentru a continua. Scriu in . Eu apas acum F5. 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. e nevoie sa ii spunem Debugger-ului sa mearga mai departe – apasam tasta F5 pentru a continua executia programului. cu galben.

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

Programul . 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.

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

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

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

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)//-->