Noţiuni introductive în .

NET şi C#
CUPRINS CURS 2-9 INTRODUCERE ÎN C#.................................................................................................................................................. 2 PROGRAMAREA ORIENTATĂ PE OBIECTE - OOP (OBJECT ORIENTED PROGRAMMING).................................. 2 CLASE ŞI OBIECTE ..................................................................................................................................................... 4 ORGANIZAREA CLASELOR ŞI COMPORTAMENTUL ACESTORA ........................................................................... 5 MOŞTENIRE SIMPLĂ SAU MULTIPLĂ ........................................................................................................................ 6 COMPUNERE SAU MOŞTENIRE ................................................................................................................................ 9 CREAREA UNEI CLASE............................................................................................................................................... 9 TRANSMITEREA ARGUMENTELOR CĂTRE METODE............................................................................................ 15 CREAREA DE OBIECTE ............................................................................................................................................ 20 TIPURI DE DATE ÎN .NET FRAMEWORK.................................................................................................................. 26 TIPURI FUNDAMENTALE .......................................................................................................................................... 26 TIPURI PRIMITIVE...................................................................................................................................................... 26 TIPURI REFERINŢĂ ŞI TIPURI VALOARE ................................................................................................................ 27 TIPURI AUXILIARE..................................................................................................................................................... 33 TIPURI SEALED ......................................................................................................................................................... 33 TIPURI IMUTABILE..................................................................................................................................................... 34 CASTINGUL ŞI CONVERSIA OBIECTELOR ŞI TIPURILOR PRIMITIVE .................................................................. 34 CASTINGUL ÎNTRE TIPURI PRIMITIVE..................................................................................................................... 35 CASTINGUL OBIECTELOR........................................................................................................................................ 35 CONVERSIA TIPURILOR PRIMITIVE ÎN OBIECTE ŞI INVERS................................................................................. 36 COMPARAREA OBIECTELOR................................................................................................................................... 36 DECLARAREA VARIABILELOR ................................................................................................................................. 36 OPERATORI ............................................................................................................................................................... 37 INSTRUCŢIUNI ÎN C#................................................................................................................................................. 38 NAMESPACES ........................................................................................................................................................... 38 DELEGAŢI ŞI EVENIMENTE ...................................................................................................................................... 39 COMPILATORUL C# .................................................................................................................................................. 42 OPTIMIZARE .............................................................................................................................................................. 42 ASSEMBLY-URI.......................................................................................................................................................... 43 PREPROCESOR ........................................................................................................................................................ 43 RESURSE................................................................................................................................................................... 43 DIVERSE .................................................................................................................................................................... 44 COLECŢII DE DATE ................................................................................................................................................... 44 INTERFEŢE ÎN SYSTEM.COLLECTIONS .................................................................................................................. 45 IENUMERATOR ŞI IDICTIONARYENUMERATOR .................................................................................................... 45 INTERFAŢA IENUMERABLE...................................................................................................................................... 46 ICOLLECTION ............................................................................................................................................................ 46 ILIST............................................................................................................................................................................ 47 IDICTIONARY ............................................................................................................................................................. 47 HASHTABLE............................................................................................................................................................... 48 DE REŢINUT… ........................................................................................................................................................... 52

Curs M I- 2-3-4-5-6-7-8

© Copyright by EBS Romania S.R.L.

Pagina 1 din 52

Noţiuni introductive în .NET şi C#
Introducere în C#.
Programare orientată pe obiecte o Clase şi obiecte; o Modificatori de acces; o Constructori şi destructori; o Metode. Overload, override, virtual; o Proprietăţi şi indexatori; o Conceptul de moştenire în C#. Compunere şi moştenire; o Interfeţe; o Clase concrete şi abstracte; Tipuri de date în .NET Framework Tipuri fundamentale o Tipuri primitive o Tipuri referinţă şi tipuri valoare Tipuri auxiliare o Tipuri sealed o Tipuri imutabile Casting; Declararea variabilelor; Operatori; Instrucţiuni în C#; Namespaces; Evenimente şi Delegaţi; Compilatorul C#. Rularea programelor. Tablouri, Liste şi Colecţii o Array, ArrayList, BitArray o Colecţii de date o Interfeţe în System.Collections C# (se pronunţă “C şarp”) este un limbaj de programare simplu, modern, orientat obiect şi “Type-Safe” (acces securizat la proprietăţile obiectelor). Programatorilor cu experienţă în C sau C++ le va fi foarte familiar. C# combină productivitatea înaltă a limbajelor RAD (Rapid Application Development ) şi facilităţile oferite de C++. Programarea orientată pe obiecte - OOP (Object oriented programming) Programarea obiectuală aduce cu siguranţă multe beneficii. S-a făcut multă vâlvă în jurul acestui concept, multora li se pare greu de înţeles, aşa cum greu de pătruns este şi utilitatea unei astfel de abordări. Dar pentru un programator care a creat prima aplicaţie mai complexă, beneficiile devin evidente. Programarea obiectuală este de fapt a face ordine, a aduce claritate şi limpezime, a face uşor de înţeles, a crea perspective pentru dezvoltări ulterioare într-o activitate care devine tot mai complexă şi dinamică, cum este aceea de dezvoltare de aplicaţii. În acest curs vor fi prezentate conceptele de bază ale OOP (Object-oriented programming), exemple create în C#, încercându-se o familiarizare cu acest stil de programare ca pas înainte faţă de programarea procedurală. Alan Kay a descris cinci caracteristici de bază ale Smalltalk-ului, primul limbaj de succes orientat obiect şi unul din limbajele care stau la bazele C#. Aceste caracteristici reprezintă chintesenţa programării orientate obiect:
Curs M I- 2-3-4-5-6-7-8 © Copyright by EBS Romania S.R.L. Pagina 2 din 52

Noţiuni introductive în .NET şi C#
1. Orice este un obiect. Un obiect este văzut ca o variabilă oarecare, care stochează date, dar unui obiect i se pot adresa cereri de a executa anumite operaţii asupra lui însuşi. În teorie, poţi lua orice componentă a problemei care se vrea rezolvată (câini, clădiri, servicii) şi să o reprezinţi ca un obiect. 2. Un program este o colecţie de obiecte, care îşi spun unul altuia ce să facă prin trimiterea de mesaje. Pentru a face o cerere la un obiect, trebuie să-i trimiţi un mesaj. Mai exact, mesajele pot fi văzute ca cereri de apel al unei funcţii care aparţine acelui obiect. 3. Fiecare obiect dispune de propria lui memorie construită din alte obiecte. Altfel spus, poţi crea un nou tip de obiect prin crearea unui pachet care conţine alte obiecte existente. Altfel, se pot crea programe de o complexitate ridicată, ascunsă în spatele simplicităţii obiectelor. 4. Fiecare obiect are un tip. Cu alte cuvinte fiecare obiect este o instanţă a unei clase, unde cuvântul “clasa” este sinonim cu cuvântul “tip”. Cea mai importantă caracteristică distinctă a unei clase este: “Ce mesaje i se pot trimite?” 5. Toate obiectele de un anumit tip pot primi aceleaşi mesaje. Aceasta de fapt se subînţelege, deoarece dacă un obiect de tip “Cerc” este de asemenea şi un obiect de tip “forma geometrică”, atunci obiectul “cerc” sigur va accepta mesaje de tip “forma geometrică”. Booch oferă chiar o descriere şi mai succintă a unui obiect:
“An object has state, behaviour and identity” (Un obiect are stare, comportament şi identitate)

Acest lucru înseamnă că un obiect poate avea date interne (de unde rezultă starea lui), metode (care dau comportamentul obiectului) şi fiecare obiect poate fi delimitat faţă de oricare alt obiect, altfel spus fiecare obiect are o adresă unică în memorie. Programarea orientată obiect este un concept remarcabil – chiar dacă în realitate nu este foarte “modern”, el apărând ideatic încă din anii ‘70! Ideea centrală este destul de simplă şi clară: organizaţi programele în aşa fel, încât să oglindească modul cum sunt organizate obiectele din lumea reală. Un program este privit în general ca o listă de instrucţiuni care îi spun calculatorului ce are de făcut. Un program este considerat de OOP drept un set de obiecte care lucrează împreună cu scopul de a îndeplini o sarcină. Să luăm ca exemplu un model practic extrem de întâlnit în aceste zile - construirea unui PC din diferite componente separate (placă de bază, placă video, procesor, etc.). Intern, fiecare dintre aceste componente poate fi extrem de complicată şi complexă, dar cel ce asamblează întregul nu are nevoie să ştie exact detaliile de funcţionare internă a fiecărei componente, ci doar câteva date foarte concrete: se vor potrivi aceste componente la nivel fizic? vor putea lucra împreună din punct de vedere funcţional aceste componente? Odată cunoscute interacţiunile dintre componente, realizarea sistemului final va fi destul de simplă. Programarea orientată obiect se mulează perfect pe exemplul anterior: programul nostru final se compune din mai multe componente – obiecte care trebuie să interacţioneze cu succes. Un obiect este un element independent al unui program, care reprezintă un set de caracteristici corelate şi este proiectat pentru a realiza anumite sarcini. Obiectele mai sunt numite şi instanţe.

Curs M I- 2-3-4-5-6-7-8

© Copyright by EBS Romania S.R.L.

Pagina 3 din 52

Noţiuni introductive în .NET şi C#
Clase şi Obiecte O clasă este un model (şablon) folosit pentru a crea mai multe obiecte cu aceleaşi caracteristici. Clasele înglobează toate caracteristicile unui anumit set de obiecte. Atunci când scriem un program într-un limbaj OOP, nu definim obiecte, ci clase de obiecte, acestea fiind modelele după care se generează obiectele. Atunci când programul rulează din aceste clase sunt create obiecte, acestea fiind apoi folosite. Sarcina programatorului este de a crea seturile corecte de clase pentru ca programul să se comporte corespunzător. În practică, nici măcar nu trebuie pornit de la zero cu construcţia claselor, deoarece .NET Framework SDK conţine un grup de clase care implementează caracteristicile de bază de care au în general nevoie programatorii. Aceste grupe de clase se numesc biblioteci. O bibliotecă de clase este un grup de clase proiectate pentru a fi folosite împreună cu alte programe. Odată cu avansarea în programarea C#, se poate crea un set complet nou de clase care să aibă definite anumite interacţiuni între ele; acestea pot fi folosite pentru a se alcătui eventual o bibliotecă proprie de clase care poate fi reutilizată mai târziu în alte programe. Această capacitate de reutilizare este unul dintre avantajele majore ale programării orientate obiect. Între programatorii care lucrează cu obiecte se disting programatori care creează clase şi programatori de tip client, care folosesc aceste clase în aplicaţiile proprii, pentru aceştia fiind important să dispună de o suită de clase cât mai complete. Creatorii de clase ar trebui să expună în clasele pe care le construiesc doar elementele de care au nevoie programatorii client. De ce? Pentru că tot ceea ce este ascuns nu poate fi folosit din exterior şi acele porţiuni de cod pot fi schimbate fără a afecta utilizatorii clasei. Stabilirea acestui domeniu de vizibilitate se realizează prin folosirea unor modificatori de acces: PUBLIC, PRIVATE, PROTECTED şi INTERNAL. Când o clasă se defineşte ca fiind de tip PUBLIC, poate fi accesată de oricine, pe când dacă este definită PRIVATE nu este accesibilă decât intern. Modificatorul PROTECTED acţionează ca şi private, cu deosebirea că această clasă este accesibilă şi din clasele derivate (subclase), iar o clasă definită INTERNAL este accesibilă din orice altă clasă care face parte din acelaşi namespace. În C#, dacă nu este specificat nici un modificator de acces, cel implicit este INTERNAL. Proprietăţile reprezintă parametri individuali care diferenţiază o clasă de obiecte de o alta şi care determină modul de prezentare, starea şi alte calităţi ale clasei. Într-o clasă proprietăţile sunt definite de variabile. Fiecare obiect poate avea valori diferite ale variabilelor sale; acestea se numesc variabile de instanţă. O variabilă de instanţă este un element de informaţie care defineşte proprietarul unui anumit obiect. Clasa obiectului defineşte ce fel de proprietate este şi fiecare instanţă îşi păstrează propria sa valoare pentru acea proprietate. Variabilele de instanţă mai sunt denumite şi variabilele obiectului. Fiecărei proprietăţi a unei clase îi corespunde o singură variabilă; putem schimba proprietatea unui obiect modificând această variabilă. Variabilele de instanţă pot lua o valoare atunci când se creează un obiect ce rămâne neschimbat pe toată durata lui de existenţă sau pot lua diferite valori pe măsură ce obiectul este folosit. O altă proprietate este folosită pentru descrierea întregii clase de obiecte, nu numai a unui singur obiect al clasei. Aceste proprietăţi sunt conţinute în variabile de clasă. O asemenea variabilă se mai numeşte şi STATICĂ. O variabilă de clasă este un element de informaţie care defineşte proprietatea unei întregi clase. Variabila se aplică însăşi clasei şi tuturor instanţelor ei, deci este stocată o singură valoare, indiferent de câte obiecte ale clasei au fost create. Indexatorii sunt elemente care pot identifica un element într-o colecţie. Am putea crede, la o primă vedere, că un astfel de rol îl pot avea doar variabilele de tip întreg (cum sunt indicii unui vector). Indexatori pot fi însă şi string-urile şi alte elemente.

Curs M I- 2-3-4-5-6-7-8

© Copyright by EBS Romania S.R.L.

Pagina 4 din 52

Noţiuni introductive în .NET şi C#
De exemplu, în colecţia de coloane a unei tabele putem identifica o anumită coloană şi prin numele ei: DataTable.Columns[2] sau DataTable.Columns["Prenume"]. În definirea unei clase, un indexator se defineşte la fel ca o proprietate, cu diferenţa că numele acestei “proprietăţi” este întotdeauna this:
public object this[int index] { get { if (!ValidIndex(index)) throw new Exception("Index in afara intervalului valid"); else return GetNode(index).Value; } set { if (!ValidIndex(index)) throw new Exception("Index in afara intervalului valid"); else GetNode(index).Value = value; } }

Comportamentul unei clase este modul în care clasele de obiecte pot face ceva cu ele însele sau cu alte obiecte. Comportamentul unei clase determină ce obiecte ale clasei îşi modifică proprietăţile, precum şi ce fac ele atunci când alte obiecte le cer să facă ceva. Comportamentul unei clase de obiecte este determinat cu ajutorul metodelor. Metodele sunt grupuri de instrucţiuni dintr-o clasă de obiecte, care acţionează asupra acesteia sau asupra altor clase sau obiecte. Ele sunt folosite pentru a realiza diferite sarcini, în acelaşi fel în care în alte limbaje de programare se folosesc funcţiile. Obiectele comunică unele cu altele folosind metodele. O clasă sau un obiect poate apela metode dintr-o altă clasă sau obiect pentru mai multe motive: pentru a raporta o modificare unui alt obiect; pentru a comunica altui obiect să modifice ceva în legătură cu el; pentru a cere unui obiect să facă ceva. Aşa cum există variabile de instanţă şi de clasă, există şi metode de instanţă şi de clasă. Metodele de instanţă, numite şi simplu „metode”, acţionează asupra unui obiect al clasei. Dacă o metodă efectuează schimbări doar asupra unui obiect individual, ea trebuie să fie o metodă de instanţă. Metodele de clasă acţionează asupra clasei însăşi. Organizarea claselor şi comportamentul acestora Moştenirea reprezintă unul dintre cele mai importante concepte ale programării OOP, având un efect direct asupra modului de proiectare şi scriere a claselor noastre C#. Moştenirea este un mecanism care permite unei clase să moştenească comportamentul şi atributele unei alte clase. Prin moştenire, o clasă dobândeşte imediat tot comportamentul unei clase existente. Din acest motiv, noua clasă poate fi creată prin simpla specificare a diferenţelor faţă de clasa existentă. Prin moştenire, toate clasele sunt aranjate într-o ierarhie strictă – cele pe care le creăm şi cele provenite din biblioteca .NET Framework sau din alte biblioteci. O clasă care moşteneşte altă clasă este denumită subclasă sau clasă derivată, iar clasa care îşi oferă moştenirea se numeşte superclasă sau clasă de bază.
Curs M I- 2-3-4-5-6-7-8 © Copyright by EBS Romania S.R.L. Pagina 5 din 52

care moşteneşte o clasă existentă. iar fiecare obiect îşi completează informaţiile corespunzătoare acestei situaţii. poate avea însă un număr nelimitat de subclase. dorim ca ea să prezinte toate caracteristicile unei clase existente. Fiecare clasă aflată mai jos în ierarhie devine din ce în ce mai adaptată unui scop precis. Problema se complică atunci când o subclasă defineşte o metodă cu acelaşi nume. În mod normal. Dacă metoda nu este găsită. Moştenirea simplă face ca relaţiile între clase şi comportamentul pe care aceste clase îl implementează să devină uşor de înţeles şi de proiectat. mai ales atunci când avem un comportament similar care trebuie duplicat pe diferite ramuri ale ierarhiei de clase. Subclasarea reprezintă crearea unei noi clase. deoarece fiecare clasă C# poate avea o singură superclasă. unde clasa Cerc a moştenit clasa FormaGeometrică.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Cerc şi Cilindru). într-o subclasă putem crea o metodă cu acelaşi nume.NET Framework . aceste concepte devin din ce în ce mai concrete odată cu coborârea spre subclase. dacă definim o clasă care nu specifică o superclasă. Subclasele moştenesc toate proprietăţile şi comportamentul superclaselor lor. Object reprezintă cea mai generica clasă din ierarhie. tip de rezultat şi argumente care sunt definite şi într-o superclasă. dar în acelaşi timp şi o superclasă pentru clasa Cilindru (exemplu suprascriere constructor). Ea poate fi însă restrictivă. Acest lucru îi permite acesteia să se integreze corect în ierarhia claselor C#. Astfel. C# rezolvă această problemă a comportamentului partajat prin folosirea interfeţelor. Pagina 6 din 52 . atunci C# presupune automat că noua clasă moşteneşte direct clasa Object. Când clasa noastră defineşte un comportament complet nou şi nu este o subclasă. în practică. fiecare implementând proprietăţi noi. şi în C++. Acest lucru este determinat dinamic. care defineşte comportamentul şi proprietăţile moştenite de toate clasele din biblioteca . clasele pot avea mai multe superclase. C# simplifică acest concept permiţând doar moştenirea simplă. Atunci când creăm un nou obiect.R. Deci clasa Cerc este o subclasă a clasei FormaGeometrică. Moştenire simplă sau multiplă Forma de moştenire folosită în C# este denumită moştenire simplă. atunci când o metodă este folosită într-un program aflat în execuţie. când creăm o nouă clasă C#. interpretorul C# verifică mai întâi clasa obiectului pentru a găsi acea metodă. Dacă apelăm o metodă a unui anumit obiect. În paragrafele următoare vor fi definite 3 clase (FormaGeometrică.L. C# păstrează urma fiecărei variabile definite pentru acel obiect şi a fiecărei variabile definite pentru fiecare clasă a obiectului. acest lucru complică mult definiţia clasei şi a codului necesar pentru producerea acesteia. Singurul lucru care trebuie făcut în subclasă este definirea diferenţelor în comportament şi proprietăţi faţă de superclasă. În acest fel. cu unele modificări. moştenind variabile şi metode combinate din toate aceste superclase. interpretorul o caută în superclasa clasei şi aşa mai departe până la găsirea definiţiei metodei. În alte limbaje de programare. tip de rezultat şi argumente ca ale metodei din superclasă. atunci ea moşteneşte direct clasa Object. Această formă de moştenire este denumită moştenire multiplă şi oferă mijloace de creare a unor clase care cuprind aproape orice comportament imaginabil. În acest caz se foloseşte definiţia metodei care este găsită prima (începând din partea de jos a ierarhiei şi mergând în sus). iar clasa Cilindru a moştenit clasa Cerc.Noţiuni introductive în . toate clasele se combină pentru a forma un model al obiectului curent. Totuşi. Metodele se comportă în acelaşi fel: noile obiecte au acces la toate metodele clasei şi superclaselor de care aparţin. aceasta procedură se numeşte anulare prin suprascriere sau simplu suprascriere.NET şi C# O clasă poate avea o singură superclasă. În vârful ierarhiei de clase C# se află clasa Object – toate clasele moştenesc această unică superclasă. O ierarhie de clase defineşte conceptele abstracte la vârful ierarhiei. Curs M I.

O metodă abstractă este implicit şi o metodă virtuală. Tehnic vorbind. Pentru a rezolva această problemă vom defini o interfaţă IMijlocFix cu metodele specifice. care determină ca o clasă să nu poată fi moştenită. O clasă abstractă este o clasă care conţine doar definiţii şi care se vrea doar o clasă de bază (superclasă) pentru alte clase. etc. Toate acestea vor avea metode de calcul amortizare. O metodă abstractă nu conţine implementări. Unei clase abstracte nu i se poate folosi modificatorul sealed. } În definiţiile claselor amintite vom specifica faptul că aceste clase implementează şi interfaţa IMijlocFix: class Articol: IMijlocFix { void IMijlocFix. Pentru definirea unor caracteristici comune ale unui set (sau unei ierarhii) de obiecte utilizează în multe situaţii clasele abstracte.CalculAmortizare { // Cod specific pentru implementarea metodei în clasa Articol } void IMijlocFix.2-3-4-5-6-7-8 © Copyright by EBS Romania S. acestea vor putea fi privite la un moment dat din punct de vedere al unui contabil ca mijloace fixe.NET şi C# O interfaţă este o colecţie de metode care indică faptul că o clasă are un anumit comportament suplimentar faţă de ceea ce moşteneşte de la superclasele sale. Curs M I. Acest modificator poate defini clase. O subclasă derivată din clasa abstractă trebuie să implementeze toate metodele abstracte moştenite. Este de reţinut faptul că în definirea unei interfeţe nu se specifică nimic referitor la conţinutul metodelor şi că o clasă care implementează o interfaţă trebuie să conţină în mod obligatoriu codul pentru implementarea fiecărei clase din interfaţă. De exemplu: public abstract void MetodaMea().ModificValoare(int suma) { // cod specific pentru implementarea metodei în clasa Articol } } În acelaşi mod se vor implementa metodele specifice interfeţei şi în celelalte clase. O astfel de clasă se defineşte folosind modificatorul abstract. care la rândul lor conţin doar declaraţii. metode şi proprietăţi. void ModifcValoare(int suma). o interfaţă C# nu conţine nimic altceva decât definiţii de metode abstracte şi constante. de exemplu. fără variabile de instanţă sau implementări de metode. O clasă poate moşteni (implementa) mai multe interfeţe. avem clasele Articol.L. reevaluare. dar poate deriva o singură clasă de bază (moştenire simplă). Pagina 7 din 52 .R. Dacă. Clasele abstracte au următoarele caracteristici: O clasă abstractă nu poate fi instanţiată. în felul următor: public interface IMijlocFix { void CalculAmortizare(). O clasă abstractă poate conţine metode abstracte. virtual sau override. Autoturism şi Strung.Noţiuni introductive în . Unei metode definite abstracte nu i se mai pot asocia următoarele cuvinte cheie: static.

protected int y = 150. } public abstract int GetY // Proprietate Abstractă { get.NET şi C# Metoda abstractă va fi implementată doar în clasele derivate prin suprascriere.Noţiuni introductive în . Clasa1. Clasa1.GetY).L. } } public override int GetY // suprascrierea proprietăţii { get { return y+10. Clasa abstractă conţine o metodă abstractă MetodaMea şi două proprietăţi abstracte GetX() şi GetY(). // claseAbstacte. O clasă abstractă care implementează o interfaţă poate transpune în metode abstracte metodele interfeţei. } public override int GetX // suprascrierea proprietăţii { get { return x+10. y = 161 Curs M I. Clasa1.Read(). // Metodă Abstractă public abstract int GetX // Proprietate Abstractă { get. } } class SubClasa: SuperClasa { public override void MetodaMea() { x++. y = {1}". public abstract void MetodaMea(). Pagina 8 din 52 .MetodaMea(). Console. Console.WriteLine("x = {0}. y++.2-3-4-5-6-7-8 © Copyright by EBS Romania S. În următorul exemplu clasa SubClasa moşteneşte clasa abstractă SuperClasa.GetX.R. } } /* Output x = 111. } } public static void Main() { SubClasa Clasa1 = new SubClasa().cs abstract class SuperClasa // Clasă Abstractă { protected int x = 100.

public ArrayList aList. acest lucru nefiind posibil prin compunere. pentru două clase de tip Tractor şi Camion metodele comune pot fi descrise într-o clasă de bază comună Autovehicol). un obiect dintr-o clasă compusă poate fi înlocuit la run-time cu alt obiect de acelaşi tip. toate modificările se vor transfera automat în toate subclasele derivate. obiecte care nu pot avea în ierarhia de moşteniri o clasă abstractă comună (de ex. Crearea unei clase Precum am observat deja.Noţiuni introductive în . dacă modificăm o clasă abstractă. Acest fapt este util atunci când vom crea componente care au mai multe versiuni.2-3-4-5-6-7-8 © Copyright by EBS Romania S. interfeţele sunt utile în special atunci când dorim să transpunem un anumit comportament unor obiecte foarte diferite (vezi exemplul de la interfeţe). Care ar fi diferenţele între cele două abordări? Iată câteva: prin moştenire avem acces la detaliile interne de implementare ale clasei părinte (elementele declarate protected).NET şi C# */ Pentru a înţelege conceptele de interfaţă şi clasă abstractă (care în Visual Basic se definesc cu MustInherit) este necesar să facem câteva lămuriri suplimentare: o clasă abstractă poate conţine şi metode care nu sunt abstracte (deci poate conţine cod pentru implementarea metodelor). public class Stiri { // corpul clasei } Curs M I. } şi În primul caz am creat o clasă nouă prin compunere. Pagina 9 din 52 .L. prin compunere se pot crea clase noi înglobând funcţionalităţile mai multor clase.R. o clasă se defineşte folosind cuvântul cheie “class”. modificarea unei interfeţe cere în mod obligatoriu modificarea tuturor claselor care moştenesc interfaţa respectivă (dacă apare o metodă nouă este obligatorie implementarea ei în toate clasele care moştenesc interfaţa). în al doilea am creat o clasă prin moştenire. ceea ce nu este posibil prin moştenire (moştenire simplă). Acest cuvânt a fost pentru prima dată folosit în limbajul orientat obiect Simula-67. dar poate moşteni mai multe interfeţe. Compunere sau moştenire Comparaţi următoarele două definiţii: class oLista { private int x. } class oLista:ArrayList { private int x. dacă se doreşte suprascrierea unei astfel de metode ea trebuie declarată virtuală. un obiect poate deriva o singură clasă abstractă.

ca în exemplul de mai jos: public class Dinozaur: Reptile { String culoare.13).Y). int varsta. Expresiile cu punct sunt evaluate de la stânga spre dreapta. variabila de instanţă sau de clasă este formată din două părţi: obiectul.Drawing. în partea dreaptă. pozitie. Această formă de accesare a variabilelor este o expresie (deoarece întoarce o valoare) în care de ambele părţi ale punctului se află tot expresii. pozitie. în afara metodelor.WriteLine("\nSe muta in (7.rezervat.R. Acest comportament este definit prin specificarea variabilelor şi metodelor noii clase. trebuie precizat comportamentul noii clase. folosim următoarea sintaxă pentru a indica superclasa noii clase: public class StiriSportive: Stiri { // corpul clasei } Atunci când creăm o clasă care moşteneşte o superclasă.Noţiuni introductive în . String sex.L. Pagina 10 din 52 . Principala diferenţă constă în localizarea acestora în cadrul clasei.6)"). Console. Atribuirea unei valori acelei variabile se face pur şi simplu prin utilizarea operatorului de atribuire: clientulMeu. Dacă variabila totalFactura referă ea însăşi un obiect. În continuare avem un exemplu simplu de accesare a variabilelor prin notaţia cu punct: public class DefinirePuncte { static void Main(string[] args) { System.totalFactura. în partea stângă a punctului şi variabila. Variabilele de instanţă sunt declarate şi definite asemănător celor locale.WriteLine("X egal "+pozitie. bool flamand. În final vom obţine valoarea variabilei rezervat . Console.X=7. totalFactura. toate clasele moştenesc clasa Object. putem să ne referim la aceasta astfel: clientulMeu.rezervat=true.Y=6.Point pozitie=new System. care este superclasa tuturor claselor din ierarhia C#. care o face să difere de superclasa sa.2-3-4-5-6-7-8 © Copyright by EBS Romania S.X). În această notaţie. De exemplu.totalFactura.Drawing.WriteLine("Y egal "+pozitie. care referă un alt obiect cu variabila rezervat. care posedă propria variabilă de instanţă numită rezervat. atunci ne vom referi la această variabilă astfel: clientulMeu. aşa încât se va începe cu variabila din clientulMeu.totalFactura. Console.Point(4. Console.WriteLine("Pozitia de inceput:"). } Pentru a obţine valoarea unei variabile de instanţă vom folosi notaţia cu punct.NET şi C# În mod prestabilit. Dacă clasa este o subclasă. Acest lucru înseamnă că putem insera mai multe variabile de instanţă. Curs M I. dacă avem un obiect atribuit variabilei clientulMeu şi acel obiect posedă o variabilă denumită totalFactura.

Variabilele de clasă folosesc la comunicarea între diferite obiecte ale aceleiaşi clase sau pentru păstrarea unor informaţii comune la nivelul întregii clase.Y). putem folosi un tip special de variabilă. Modificarea valorii sale este vizibilă în toate instanţele clasei.MembruFamilie. qualify it with a type name instead Console.WriteLine("Y egal "+pozitie. nefiind stocate individual în obiectele (instanţele) clasei. însă variabila de clasă numeFamilie are o valoare comună pentru toţi membrii familiei. fiecare nouă instanţă primea o copie a variabilelor de instanţă definite în clasă. String prenume. ca mai jos: static int suma.R. numit constantă. toate instanţele clasei MembruFamilie vor fi afectate. Console.NET şi C# Console.WriteLine("Pozitia finala:").numeFamilie).WriteLine("Numele "+MembruFamilie. Console.Noţiuni introductive în .2-3-4-5-6-7-8 © Copyright by EBS Romania S. Console. Pagina 11 din 52 . În cazul variabilelor de clasă există o singură copie a acesteia. Curs M I. Pentru accesarea acestor variabile de clasă se foloseşte aceeaşi notaţie cu punct. Dacă valoarea nu se schimbă niciodată pe parcursul execuţiei programului. Pentru a obţine sau modifica valoarea unei variabile de clasă în partea stângă a punctului folosim numele clasei. În cazul variabilelor de instanţă. Pentru a declara o variabilă de clasă se foloseşte cuvântul cheie static.X). Dacă folosim numele instanţei.Read().numeFamilie' cannot be accessed with an instance reference. Să luăm de exemplu următoarea definiţie de clasă: class MembruFamilie { static String numeFamilie="Popescu". // Eroare: Static member 'exemple. int varsta. compilatorul va semnala o eroare: class MembruFamilie { static String numeFamilie="Popescu". } } Variabilele de clasă se aplică unei clase în întregul său. } Instanţele clasei noastre posedă propriile valori pentru prenume şi vârstă. String prenume. static final int maxObiecte=10. public static void Main() { MembruFamilie tata=new MembruFamilie().WriteLine("Numele "+tata. int varsta. } } Variabilele sunt folositoare atunci când avem nevoie să păstrăm informaţii ce vor fi modificate pe parcursul rulării programului. Fiecare instanţă poate modifica apoi valorile acestor variabile fără a afecta alte instanţe. Dacă se modifică valoarea acestei variabile. Console.WriteLine("X egal "+pozitie.numeFamilie).L.

de clasă sau locale. Constantele pot fi folositoare la denumirea diferitelor stări ale unui obiect sau la testarea acestor stări. Aceşti parametri devin variabile locale în corpul metodei. o listă de parametri. atunci când metoda nu returnează o valoare.1415.Noţiuni introductive în .poate fi un tip primitiv. ca în exemplele de mai jos: final float pi=3. Metodele definesc comportamentul unui obiect – acţiunile efectuate la crearea obiectului sau pe parcursul duratei sale de viaţă. Pentru a declara o constantă folosim cuvântul cheie final înainte de declararea variabilei şi atribuim valoarea iniţială pentru variabila respectivă. Clasele şi obiectele oferă un cadru de lucru. un nume de clasă sau cuvântul cheie void. O metodă cuprinde patru părţi: modificatori de acces. numele metodei. prin cuvântul cheie return. În afara cazurilor când este declarată cu tipul de retur void.L.tipRetur . Mai jos avem un exemplu de clasă care defineşte o metodă care preia doi întregi şi creează un tablou care conţine toate numerele întregi aflate între cele două limite: Curs M I.poate fi unul din cuvintele cheie: public sau private. …) { // corpul metodei } . Folosirea constantelor uşurează de cele mai multe ori înţelegerea programului. final int telefon=8675309. final bool debug=false. Mai jos putem vedea o definiţie generală a unei metode: modificator tipRetur numeMetoda(tip1 argument1. int sup) { // corpul metodei } Lista de parametri a metodei este un set de definiţii de variabile. Doar metodele pot defini comportamentul unui obiect. În cazul în care metoda returnează un obiect tablou. Această valoare trebuie specificată explicit în punctele de ieşire ale metodei. În C# putem crea constante pentru toate tipurile de variabile: de instanţă.R.modificator . lucrurile pe care este capabil să le realizeze sau modul cum interacţionează cu alte clase sau obiecte. Variabilele de instanţă şi de clasă oferă o modalitate de a defini ceea ce reprezintă aceste clase şi obiecte.2-3-4-5-6-7-8 © Copyright by EBS Romania S. primind valori la apelarea metodei. cu alte cuvinte. o metodă returnează la terminarea sa o valoare de un anumit tip. denumită şi variabilă constantă. corpul metodei. este o variabilă a cărei valoare nu se modifică niciodată. Constantele se folosesc pentru definirea valorilor comune pentru toate metodele unui obiect. trebuie folosite parantezele pătrate fie după tipRetur fie după lista de parametri: Private int[] creareDomeniu(int inf.NET şi C# O constantă. separate prin virgula şi încadrate între paranteze rotunde. tipul obiectului sau tipul de date primitiv returnat de metodă. tip2 argument2. Pagina 12 din 52 . pentru denumirea unor valori ce nu se vor schimba în cadrul obiectului. .

Această declaraţie poate lipsi.i<unTablou.10).2-3-4-5-6-7-8 © Copyright by EBS Romania S.L. static – înseamnă că metoda Main() este o metodă de clasă.Write("Tabloul: [ "). aici poate fi şi tipul int.Length. Curs M I. } [STAThread] public static void Main(string[] argumente) { int[] unTablou. O aplicaţie C# constă în una sau mai multe clase ce pot avea orice dimensiune dorim. C# le memorează sub forma unui tablou de şiruri. Clasa de pornire a aplicaţiei are nevoie de un singur lucru: o metodă Main() care este prima metodă apelată.Write("]"). Pentru a putea trata aceste argumente drept altceva decât şiruri trebuie mai întâi să le convertim.Write(unTablou[i]+" ").creareDomeniu(1. după care foloseşte un ciclu for pentru a afişa valorile noului tablou .i++) { Console. } return tabl. for (int i=0.R. ClasaDomeniu unDomeniu=new ClasaDomeniu(). unTablou=unDomeniu. for (int i=0.int sup) { int[] tabl=new int[(sup-inf)+1]. Console. de valorile 1 şi 10.Noţiuni introductive în . Semnătura metodei Main() arată astfel: public static void Main(string[] argumente) { // corpul metodei } public – înseamnă că metoda este disponibilă altor clase şi obiecte. void – înseamnă că metoda Main() nu returnează nici o valoare.i<tabl. respectiv superior.i++) { tabl[i]=inf++. Pentru a transmite argumente unui program C# acestea trebuie adăugate la execuţie după numele programului: ProgramulMeu argument1 argument2 Pentru a transmite argumente care conţin spaţii acestea trebuie încadrate de ghilimele. Pagina 13 din 52 . Main() preia un parametru care este un tablou de şiruri şi se foloseşte pentru argumentele din linia de comandă. Atunci când o aplicaţie este rulată cu argumente.NET şi C# public class ClasaDomeniu { private int[] creareDomeniu(int inf. Acest parametru poate lipsi. Singurul element de care avem neapărat nevoie pentru a rula o aplicaţie C# este o clasă care să servească drept punct de plecare pentru restul programului C#. pe care îl transmite metodei Main() a aplicaţiei.Length. } Console. } } Metoda Main() a clasei apelează metoda creareDomeniu() pentru crearea unui domeniu mărginit inferior.

Math. De exemplu.IndexOf("u")).11)).WriteLine("Sirul este: "+str).NET şi C# Apelarea unei metode a unui obiect este asemănătoare referirii variabilelor de instanţă: folosim notaţia cu punct. ca şi variabilele de clasă. Console. metoda de clasă Max().Round().WriteLine("Subsirul de la 9 la 11: "+str. Pagina 14 din 52 . iar numele metodei şi a argumentelor sale în dreapta: clientulMeu. care este definită în obiectul returnat de metoda anuleazăToateComenzile().Max(255. folosită în exemplul precedent. str. Metodele de clasă sunt utilizate de obicei drept metode de uz general.WriteLine("Radical din 10 este: {0}".Sqrt(). Curs M I. voi crede in reincarnare". se aplică unei clase în întregul său şi nu instanţelor sale. la fel ca în cazul definirii variabilelor de clasă.Substring(9.Read(). Lipsa cuvântului cheie static din faţa numelui unei metode face ca aceasta să fie o metodă de instanţă. putem imbrica metodele la fel ca la variabile. Math.Sqrt(10). Pentru a defini metode de clasă se foloseşte cuvântul cheie static.adaugInFactura(codProdus.WriteLine("Indexul caracterului u: "+str. Console. } } Metodele de clasă.ToUpper()). Console. Console.L. care nu pot opera direct asupra unei instanţe a clasei.Abs(). Console.WriteLine("Indexul inceputului "+"subsirului \"voi\": " + Console.IndexOf("voi")).WriteLine("Cel mai mare dintre x si y este:" +Math.discutăCuDirectorul(). bibliotecile . Dacă metoda apelată returnează un obiect care posedă la rândul lui metode.anuleazăToateComenzile().268)).WriteLine("Lungimea sirului este:"+str. double radical=Math. Exemplificăm folosirea unor metode definite în clasa String: class VerificareSir { public static void Main(string[] argumente) { string str="In viata mea urmatoare. Obiectul a cărui metodă o apelăm este în stânga punctului. dar se potrivesc conceptual în cadrul clasei. Console.radical).Noţiuni introductive în .Length). poziţionat în faţa definiţiei metodei.Asin(). care conţine un set larg de operaţii matematice definite ca metode de clase: Math. Console.WriteLine("Sirul scris cu litere mari: "+str. pret).NET Framework conţin o clasă denumită Math. Următorul exemplu apelează metoda discutăCuDirectorul(). Math. Metodele de clase pot fi de asemenea folositoare pentru adunarea unor metode generale într-un singur loc De exemplu. ar putea avea următoarea semnătură: public static int Max(int arg1.R. Toate metodele sunt obligatoriu urmate de paranteze – cu sau fără argumente. care a fost definită în obiectul clientulMeu: clientulMeu. int arg2) { // corpul metodei } Platforma . Console.NET Framework conţine clase de împachetare (wrapper) pentru fiecare dintre tipurile de bază.2-3-4-5-6-7-8 © Copyright by EBS Romania S.

d . nu pot folosi this.R. deci ele pot fi accesate de oricare dintre metodele din cadrul clasei. // variabila de instanţa x pentru acest obiect this. Aceste obiecte pot fi tablouri şi alte obiecte conţinute în tablouri. În corpul unei definiţii de metodă putem să ne referim la obiectul curent – obiectul a cărui metodă a fost apelată. C# verifică existenţa unei definiţii a acesteia ca variabilă de instanţă sau de clasă în clasa curentă. ca argument al unei metode. În C#. declarate prin cuvântul cheie static. Domeniul de vizibilitate este acea parte a programului în care o variabilă sau o altă informaţie poate fi folosită. subrutină sau procedură – este suficient pentru a o distinge de celelalte metode din program. în aceeaşi clasă. În alte limbaje. Atunci când referim o variabilă în cadrul unei metode. Această practică este denumită supraîncărcarea metodei (overloading). De exemplu. este afectat tabloul original. putem folosi mai multe metode cu acelaşi nume. Pentru a referi obiectul curent în astfel de cazuri se foloseşte cuvântul cheie this acolo unde în mod normal s-ar folosi numele unui obiect. Orice vom face cu obiectele în cadrul metodei le va afecta direct. Atunci când transmitem un tablou ca argument într-o metodă şi conţinutul lui se modifică.a. ca valoare de retur pentru metoda curentă ş. Curs M I. // apeleaza metoda resetDate() definita in clasa curenta si transmite obiectul curent return this. Pe de altă parte tipurile de date primitive sunt transmise prin valoare. putem să ne referim atât la variabilele de instanţă cât şi la apelurile de metode definite în clasa curentă prin simpla folosire a numelui lor. Metodele cu acelaşi nume se diferenţiază între ele prin două caracteristici: numărul argumentelor pe care le preiau. deoarece este presupus. trebuie să o folosim doar în cadrul corpului unei definiţii de metodă de instanţă .2-3-4-5-6-7-8 © Copyright by EBS Romania S. Metodele de clasă. Pagina 15 din 52 . Dacă acea parte a programului care defineşte domeniul de vizibilitate al unei variabile îşi termină execuţia. Aceasta poate avea scopul de a folosi variabilele de instanţă ale obiectului său de a transmite obiectul curent ca argument unei alte metode. după aceea în domeniul exterior imediat următor şi. O variabilă cu domeniu de vizibilitate local poate fi folosită doar în cadrul blocului în care a fost definită. Acest cuvânt cheie se referă la obiectul curent şi poate fi folosit oriunde poate apărea un obiect: în notaţia cu punct. Variabilele de instanţă şi de clasă posedă un domeniu de vizibilitate extins la întreaga clasă. în cele din urmă. Transmiterea argumentelor către metode Atunci când apelăm o metodă cu parametri de tip obiect. tipul datelor sau obiectelor fiecărui argument. deoarece this este implicit folosit în aceste referinţe: t=x. numele metodei – numită şi funcţie.Noţiuni introductive în . variabila nu mai există. C# verifică existenţa definiţiei acesteia mai întâi în domeniul de vizibilitate local.// apelează metoda resetDate() definită în clasa curentă şi transmite obiectul curent Deoarece this este o referinţă a instanţei curente a clasei. // returneaza obiectul curent În multe cazuri s-ar putea să nu fie nevoie să utilizăm explicit cuvântul cheie this.x.m.L.NET şi C# Cuvântul cheie this. Mai jos avem un exemplu de folosire a lui this: t=this. dar care diferă prin valoarea returnată sau prin lista de parametri. // variabila de instanţă x pentru acest obiect resetDate(this). obiectele sunt transmise în corpul metodei prin referinţă. Dacă nu se găseşte definiţia variabilei în clasa curentă se caută pe rând în fiecare superclasă. în domeniul metodei curente. Dacă variabila nu este locală. Relaţia dintre variabilele de instanţă şi cele de clasă este comparabilă cu diferenţa dintre modurile de lucru ale metodelor de instanţă şi de clasă.resetDate(this).

numele variabilelor pe care le alegem pentru fiecare argument nu au importanţă – tot ceea ce contează este numărul şi tipul acestora. int y1=0.x1=x1.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Pagina 16 din 52 .X. int y1. } Atunci când este creată o nouă instanţă a clasei noastre.Noţiuni introductive în . Vom crea întâi o clasă care defineşte o formă rectangulară cu patru variabile de instanţă pentru a preciza colţurile din stânga-sus şi dreapta-jos ale unui dreptunghi: x1.X. int l. } O altă modalitate de a defini un dreptunghi este de a folosi coordonatele colţului din stânga-sus. în cadrul metodei vom folosi cuvântul cheie this pentru a referi variabilele de instanţă: public DreptunghiulMeu ConstruireDreptunghi(int x1. vom obţine o eroare încă de la compilare. Menţionăm că C# nu ia în considerare tipul valorii returnate pentru a face diferenţierea metodelor supraîncărcate. astfel încât lista de argumente să conţină două obiecte Point: public DreptunghiulMeu ConstruireDreptunghi(Point stangaSus. } O altă variantă ar fi folosirea obiectelor Point în locul coordonatelor individuale. Pentru a implementa această variantă putem supraîncărca metoda noastră. int y2=0. împreună cu valorile înălţimii şi lăţimii sale: public DreptunghiulMeu ConstruireDreptunghi(Point stangaSus. în tipul de argumente sau ambele. Deoarece argumentele au acelaşi nume ca şi variabilele de instanţă. Folosirea mai multor metode cu acelaşi nume şi semnături diferite se numeşte supraîncărcare.Y. x2=dreaptaJos. y1. În continuare vom defini o metodă care preia patru argumente întregi şi returnează obiectul rectangular. int x2. Dacă încercăm să creăm două metode care diferă doar prin tipul valorii de retur.NET şi C# Aceste două caracteristici definesc semnătura metodei. return this. this. În plus. this. public class DreptunghiulMeu { int x1=0.L. Supraîncărcarea metodelor elimină nevoia de a defini metode complet diferite care să facă în principiu acelaşi lucru. int y2) { this. this.y1=y1. x2. int h) { Curs M I. În continuare vom detalia un exemplu de metodă supraîncărcată. Diferenţa poate consta în numărul de argumente. Pentru a crea o metodă supraîncărcată într-o clasă vom defini metode diferite. y2=dreaptaJos.x2=x2. C# permite supraîncărcarea metodelor atât timp cât lista de argumente este unică pentru acelaşi nume de metodă.R.Y. în funcţie de argumentele primite. int x2=0. y1=stangaSus. toate valorile vor fi iniţializate cu 0. Supraîncărcarea face de asemenea posibilă comportarea diferită a metodelor. y2.y2=y2. Point dreaptaJos) { x1=stangaSus. cu acelaşi nume însă cu liste de argumente diferite. return this.

50). return this. "+y2+">"). int y1. y1=stangaSus.X.R. y1=stangaSus. this. Point dreaptaJos) { x1=stangaSus.X.WriteLine("Apelam construireDreptunghi cu Dreptunghi.Noţiuni introductive în . y2=dreaptaJos. return this.Y.25. this. int x2. x2=(x1+l).x2=x2.WriteLine(".50. "+y1). public class DreptunghiulMeu { int x1=0.L.Y. Console. y2=(y1+h).Drawing.X. Dreptunghi. x2=(x1+l). afişareDreptunghi().Y.ConstruireDreptunghi(25. int h) { x1=stangaSus. public DreptunghiulMeu ConstruireDreptunghi(int x1. int y2=0.AfisareDreptunghi(). . Curs M I. care să apeleze toate aceste metode: using System. x2=dreaptaJos. "+x2+". Console. care urmează să afişeze coordonatele dreptunghiului şi o metodă Main().2-3-4-5-6-7-8 © Copyright by EBS Romania S. Pagina 17 din 52 coordonatele 25.WriteLine("***"). int l.25. return this.y1=y1.Y.X. } public void AfisareDreptunghi() { Console. int y2) { this. } public static void Main(string[] argumente) { DreptunghiulMeu Dreptunghi=new DreptunghiulMeu(). y2=(y1+h).NET şi C# x1=stangaSus.Write("Dreptunghiul meu: <"+x1+". int y1=0. this. } public DreptunghiulMeu ConstruireDreptunghi(Point stangaSus. } public DreptunghiulMeu ConstruireDreptunghi(Point stangaSus. y1=stangaSus.x1=x1.50: "). } Pentru a finaliza exemplul creăm încă o clasă. Console.50. int x2=0. return this.y2=y2.

un şir de metode abstracte. metoda din subclasă este găsită prima şi executată în locul celei din superclasă. Pagina 18 din 52 . } } Atunci când avem mai multe metode (din supraîncărcarea uneia) şi acestea fac lucruri asemănătoare. De exemplu.AfisareDreptunghi(). Console.WriteLine("Apelam construireDreptunghi cu punctele (10.WriteLine("***"). pot exista cazuri când dorim ca un obiect să răspundă aceloraşi metode.20): ").NET şi C# Console. new Point(20. într-o metodă putem apela o alta. } } Curs M I.Name). caută mai sus în ierarhia de clase până când găseşte o definiţie. Astfel.10). stangaSus. Totuşi. Pentru a suprascrie o metodă. Pentru ca o metodă să poată fi suprascrisă ea trebuie să fie declarată abstractă. definim într-o subclasă o metodă cu aceeaşi semnătură ca a unei metode dintr-o superclasă.Read(). tip. valoare returnată.R.Read(). trebuie să creăm în practică o metodă cu aceeaşi semnătură (nume. Console. Deci.WriteLine("x este "+x+" si y este "+y).").10). Dreptunghi.Write("Apelam construireDreptunghi cu 1 punct (10.10).WriteLine(" latime 50 si inaltime 50: ").ConstruireDreptunghi(new Point(10. atunci când metoda este apelată. Atunci când apelăm metoda unui obiect. Console.X. Procesul de moştenire a metodelor ne permite să definim şi să folosim repetat metode în subclase fără a fi nevoie să replicăm codul. } Suprascrierea metodelor (overriding) înseamnă crearea unei definiţii diferite pentru o metodă care a mai fost definită în superclasă. virtuală sau să fie suprascrisă în superclasă. Pentru a suprascrie o metodă.WriteLine("Sunt o instanţa a clasei "+this. În acest caz. public void AfisareDate() { Console. Console.Y. 50). Dacă nu o găseşte. dar să aibă un comportament diferit la apelarea acestora. dacă o clasă conţine mai mult de o definiţie. C# caută definiţia metodei respective în clasa obiectului. Dreptunghi. 50. care primeşte ca argumente două obiecte Point.AfisareDreptunghi().20)).L. şi dorim ca metodele scrise în clasă să poată fi suprascrise în eventualii descendenţi. protected int y=0. listă de argumente) ca a metodei din superclasă. în cazul de mai sus.WriteLine("***"). dreaptaJos. Dreptunghi.GetType(). Mai jos creăm un exemplu pentru a ilustra supraîncărcarea unei metode: class AfisareClasa { protected int x=0.ConstruireDreptunghi(new Point(10. va trebui ca metodele acestea să fie declarate virtuale (cuvântul cheie virtual). (20. Point dreaptaJos) { return ConstruireDreptunghi(stangaSus.Y).Noţiuni introductive în . poate fi înlocuită cu o versiune mult mai scurtă: public DreptunghiulMeu ConstruireDreptunghi(Point stangaSus.10). Console.X. Console. Dreptunghi. metoda construireDreptunghi.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Console. dreaptaJos. metoda se poate suprascrie.

comportamentul metodei originale trebuie doar completat şi nu înlocuit definitiv.NET şi C# Creăm în continuare şi o subclasă a clasei de mai sus. obiect. C# o caută în superclasă şi o găseşte acolo pentru a o putea executa. În acest fel apelul metodei este transferat mai sus în cadrul ierarhiei de obiecte: public void metodaMea (string a.AfisareDate(). subclasa conţine şi variabila z: class AfisareSubClasa: AfisareClasa { int z=3.WriteLine("Sunt o instanţa a clasei "+this. Această metodă însă nu afişează şi variabila de instanţă z. mai ales în cazurile când se realizează acelaşi tip de acţiuni şi în metoda originală şi în cea care o suprascrie. după iniţializarea obiectului AfişareSubClasa2 şi apelarea metodei afişareDate() va fi apelată versiunea existentă în subclasă şi nu cea din superclasa AfişareDate.Name). } } Acum. obiect. Pagina 19 din 52 . Compilatorul semnalează că metoda din clasa părinte nu va mai fi vizibilă. deoarece este ascunsă de implementarea din clasa curentă şi sugerează folosirea cuvântului cheie new în faţa metodei: new public void AfisareDate() { } De obicei există două motive pentru care se face suprascrierea unei metode implementate deja de o superclasă: pentru a înlocui complet definiţia metodei originale.L. } } Deoarece subclasa nu defineşte o metodă afişareDate(). string b) { Curs M I. pentru a extinde funcţionalitatea metodei originale. În multe cazuri practice. Console.Noţiuni introductive în . Să creăm o nouă subclasă care să suprascrie metoda afişareDate(): class AfisareSubClasa2: AfisareClasa { int z=3.WriteLine("x este "+x+" si y este "+y+" iar z este "+z). } public static void Main(string[] argumente) { AfisareSubClasa2 obiect=new AfisareSubClasa2(). public void AfisareDate() { Console.2-3-4-5-6-7-8 © Copyright by EBS Romania S.AfisareDate().R. Console. cu o singură diferenţă. Prin apelarea metodei originale în cadrul metodei de suprascriere putem adăuga numai însuşirea suplimentară. public static void Main(string[] argumente) { AfisareSubClasa obiect=new AfisareSubClasa().ReadLine().GetType(). Pentru a apela metoda originală în cadrul metodei de suprascriere folosim cuvântul cheie base.

se alocă memorie pentru aceasta şi se apelează constructorul. în cazul în care există argumente între ele. se creează cel mai simplu obiect.WriteLine("x este "+x+" si y este "+y). La folosirea operatorului new se creează o nouă instanţă a clasei date. deoarece este o denumire generică pentru superclasa clasei curente.WriteLine("z este "+z). folosite anterior.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Console.12). Celelalte clase C# nu au această posibilitate de creare a unui nou obiect. Parantezele sunt foarte importante: în cazul în care nu conţin argumente. Curs M I.metodaMea(a. Console. În exemplele precedente am întâlnit o instanţă a clasei String creată prin folosirea unui literal (string): string Nume="Popescu".GetType(). Îl putem folosi oriunde am putea folosi şi this. nu clasa curentă.R. Dinozaur j = new Dinozaur().} Crearea de obiecte În cele mai multe situaţii vom folosi clasele pentru a crea instanţe şi vom lucra cu aceste instanţe. după modelul căreia dorim să creăm o instanţă şi de paranteze (între care se pot găsi eventual argumente): String numeEchipa = new String(). vom obţine erori la compilarea programului. Pentru a crea un nou obiect folosim operatorul new împreună cu numele clasei. putem apela metoda originală şi adăuga doar codul suplimentar: // din AfisareSubClasa2 new public void AfisareDate() { base. însă base referă superclasa. putem modifica metoda superclasei.AfisareDate().Read(). În loc să copiem majoritatea codului metodei superclasei în subclasă. acestea determină valorile iniţiale ale variabilelor de instanţă sau ale altor calităţi iniţiale ale obiectului respectiv: Point pct=new Point(12. Console. Pagina 20 din 52 .Noţiuni introductive în . Să ne amintim de cele două metode afişareDate() diferite.NET şi C# //cod sursa base. //cod sursa Cuvântul cheie base este asemănător cuvântului cheie this. astfel încât ulterior să se poată adăuga cu uşurinţă o caracteristică suplimentară: // din afisare clasa public void AfisareDate() { Console.Name). Crearea de noi instanţe ale acestora se face explicit cu operatorul new. } } Când suprascriem metoda afişareDate() în subclasă.WriteLine("Sunt o instanţa a clasei "+this.b).L. Numărul şi tipul argumentelor pe care le folosim între paranteze împreună cu operatorul new sunt definite la definiţia clasei folosind o metodă specială denumită constructor. Dacă încercăm să creăm o nouă instanţă a clasei folosind un număr greşit de argumente sau un tip eronat al acestora.

metodele constructor nu returnează nimic. } [STAThread] public static void Main(string[] argumente) { Persoana p. Atunci când este folosită instrucţiunea new pentru crearea unui nou obiect. la fel ca metodele obişnuite. În exemplul de mai jos vom vedea o clasă Persoana. Atunci când folosim operatorul new. pentru a crea un obiect care are proprietăţi specifice.50). Prin definirea unor metode constructor în clase. int a) { nume=n. alocă memorie pentru obiect. Metodele constructor pot fi şi ele supraîncărcate. int varsta. Curs M I. La crearea unei clase putem defini oricâţi constructori avem nevoie pentru implementarea comportamentului clasei. p=new Persoana("Ion". 2.WriteLine(" si am "+varsta+" de ani"). Constructorii seamănă cu metodele obişnuite. iniţializează variabilele de instanţă ale obiectului fie la valorile iniţiale fie la cele prestabilite („o” pentru numere.Write("Eu sunt "+nume). „null” pentru obiecte. putem apela metode pe baza acestor variabile. Persoana (string n.L. } void printPersoana() { Console. Într-o clasă pot exista mai multe definiţii de constructori. Constructorii iniţializează noul obiect şi variabilele sale. putem specifica diferite argumente în lista de argumente şi va fi apelat constructorul corespunzător pentru acele argumente. o metodă constructor nu poate fi apelată direct. Console. creează orice alte obiecte de care are nevoie obiectul creat şi realizează orice alte operaţii de care obiectul are nevoie la iniţializarea sa. „false” pentru valori booleene şi “\0” pentru caractere). Pagina 21 din 52 .2-3-4-5-6-7-8 © Copyright by EBS Romania S.R.Noţiuni introductive în . cu două diferenţe: metodele constructor au întotdeauna acelaşi nume cu cel al clasei. fiecare având un număr diferit de argumente sau tipuri. putem apela metode ale altor obiecte sau putem seta proprietăţile iniţiale ale unui obiect. Chiar dacă o clasă nu are definită nici o metodă constructor. apelează metodele constructor ale clasei. este totuşi posibilă crearea unui obiect.NET şi C# Constructorii reprezintă metode pentru crearea şi iniţializarea noilor instanţe ale claselor. care foloseşte o metodă constructor pentru a-şi iniţializa variabilele de instanţă pe baza argumentelor primite de new: public class Persoana { string nume. Spre deosebire de alte metode. în funcţie de argumentele transmise prin instrucţiunea new. varsta=a. putem seta valorile iniţiale ale variabilelor de instanţă. se executa trei activităţi: 1. 3. Există însă cazuri în care dorim să setăm anumite variabile de instanţă sau să apelăm alte metode de care obiectul are nevoie pentru a se iniţializa. C# apelează metodele constructor în mod automat.

1) { } } Al doilea constructor din clasa CerculMeu preia doar coordonatele x şi y ale cercului. Console. metodele constructor nu se moştenesc. argumentele primite de this() sunt argumentele metodei constructor.Read().raza=lungRaza. arg3). Console. this. putem modifica felul în care este iniţializat obiectul nu doar prin iniţializarea noilor variabile adăugate clasei. putem apela primul constructor din interiorul celui de-al doilea.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Folosirea cuvântului cheie this într-o metodă constructor este similară modului lui de folosire pentru accesul la variabilele de instanţă ale obiectului.Noţiuni introductive în .R. Totuşi. coordY. Acest lucru a fost deja ilustrat în exemplul anterior. ci şi prin modificarea conţinutului variabilelor deja prezente. Aceasta ne permite să creăm un obiect cu proprietăţile dorite sau oferă acestuia posibilitatea de a-şi calcula proprietăţile pornind de la date de intrare diferite. Pagina 22 din 52 .y=coordY. arg2. Din punct de vedere tehnic constructorii nu pot fi suprascrişi.raza. Pentru că au întotdeauna acelaşi nume ca al clasei curente. Supraîncărcarea constructorilor. Deoarece nu este definită nici o rază. atunci când definim metode constructor pentru clasa noastră.x=coordX. p.printPersoana(). coordY şi literalul 1. Pentru aceasta vom apela explicit metodele constructor ale superclasei şi apoi vom modifica variabilele dorite. se apelează şi metoda constructor cu aceeaşi semnătură pentru toate superclasele. atunci când este apelată metoda constructor a clasei. Acest sistem este mulţumitor în marea majoritate a cazurilor. int coordY): this(coordX.WriteLine("----").30). y) ale centrului şi lungimea razei.printPersoana(). Să luăm spre exemplu o clasă care defineşte un cerc folosind coordonatele (x. ci se creează altele noi. CerculMeu (int coordX. În instrucţiunea anterioară. } CerculMeu (int coordX. Curs M I.L.NET şi C# p. Suprascrierea constructorilor. p=new Persoana("Laura". Folosim următoarea instrucţiune pentru a apela o metodă constructor definită în clasa curentă: this(arg1. Clasa CerculMeu poate avea doi constructori: unul în care este definită raza şi unul în care raza primeşte valoarea prestabilită 1: public class CerculMeu { int x. se apelează apoi prima metodă constructor care primeşte ca argumente coordX. } } Dacă avem o metodă constructor care prezintă un comportament oarecum asemănător cu cel al unui constructor existent. int lungRaza) { this. Din această cauză iniţializarea se face pentru toate părţile clasei pe care o moştenim. int coordY. se foloseşte valoarea prestabilită 1.WriteLine("----"). Ca şi metodele obişnuite constructorii pot avea un număr diferit de argumente şi/sau tipuri diferite de argumente. this. C# oferă o sintaxă specială pentru a realiza acest lucru.y. Console.

.z) şi returnează un obiect FormaGeometrica. folosind base() (fără argumente). Ex.Nume=nume. double y. putem crea o clasă care are constructori cu semnături total diferite de oricare dintre constructorii superclasei.) apelează metoda constructor pentru superclasa imediat următoare (care la rândul său va apela constructorul superclasei sale şi aşa mai departe).NET şi C# Pentru a apela o metodă obişnuită aparţinând superclasei vom folosi sintaxa: base.0) { } public Cerc(double raza.. public Cerc(double raza): base(raza. suprascriere constructor: using System.2-3-4-5-6-7-8 © Copyright by EBS Romania S. arg2. abstract class FormaGeometrica { public const double pi = Math. Clasa Cerc conţine o variabilă de instanţă suplimentară şi defineşte un constructor care iniţializează raza şi numele.0) { this. C# face acest lucru implicit. double z) { this. Nu trebuie să apelăm constructorul din superclasa care are aceeaşi semnătură cu cea a constructorului clasei noastre.).. this. Dacă nu apelăm base() explicit în cadrul constructorului. } } public abstract double Suprafata().y. .. Clasa FormaGeometrica are un constructor care preia ca argumente 3 integer (x.z = z.0. De fapt. Pagina 23 din 52 . Deoarece metodele constructor nu au nume sub care pot fi apelate.. protected double x. z. this. care extinde clasa FormaGeometrica..nume_metoda(lista_argumente). public FormaGeometrica (double x.PI. } public override double Suprafata() { return pi*x*x.L.x = x. base(. class Cerc: FormaGeometrica { private string Nume="". La fel ca în folosirea this(. } public string NumeCerc Curs M I. trebuie doar să apelăm constructorul pentru valorile pe care dorim să le iniţializăm. În exemplul următor vom prezenta o clasă Cerc.R.0. Compilatorul C# verifică aceste lucruri atunci când încercăm să compilăm fişierul sursă.y = y. vom folosi următoarea formă: base(arg1.Noţiuni introductive în . y.) într-o metodă constructor. string nume): base(raza. Reţinem că în superclasă trebuie să existe un constructor cu semnătura respectivă pentru ca apelul base() să funcţioneze.

Când un obiect este distrus.Suprafata()). de exemplu pentru distrugerea referinţelor către alte obiecte.2-3-4-5-6-7-8 . © Copyright by EBS Romania S.Cerc1. nu pot fi nici supraîncărcaţi. Pagina 24 din 52 Curs M I. Console.WriteLine("Suprafata '{0}' este = {1:F2}".Read().Noţiuni introductive în . ci sunt apelaţi automat în momentul în care nu mai există nici o referinţă către respectivul obiect. Cilindru Cilindru1 = new Cilindru(raza. double inaltime): base(raza) { y = inaltime.NET şi C# { get { } return Nume. unul dintre ei primeşte şi parametrul „nume” care iniţializează variabila de instanţă nume. Cilindru1. inaltime).R. Cerc1.WriteLine("Destructorul clasei A "). } } class TestClass { public static void Main() { double raza = 2.5. } } Metoda constructor definită aici pentru Cerc apelează metoda constructor a clasei FormaGeometrica pentru a iniţializa variabila de instanţă x. } } class Cilindru: Cerc { public Cilindru(double raza. iar metodele de finalizare sunt apelate chiar înainte de distrugerea obiectului şi recuperarea memoriei ocupate. } public override double Suprafata() { return 2*(base.0. În cadrul destructorilor. O metodă constructor este folosită pentru a iniţializa un obiect. Destructorii nu pot fi moşteniţi şi. din moment ce nu primesc nici un parametru. Destructorii sunt folosiţi de obicei pentru optimizarea distrugerii unui obiect. Clasa Cerc are doi constructori. Console. putem specifica toate acţiunile de “curăţare” pe care dorim să le realizăm în legătură cu obiectul.Suprafata()).NumeCerc. Metodele de finalizare sunt opusul metodelor constructor şi se mai numesc şi destructori.Suprafata()) + 2*pi*x*y. Exemplul următor exemplifică folosirea destructorilor: class A { ~A() { Console. inaltime = 3. Destructorii nu pot fi apelaţi direct. sunt apelaţi automat toţi destructorii ierarhiei de clase din care face parte respectivul obiect. (y şi z sunt iniţializate cu 0).WriteLine("Suprafata cilindrului= {0:F2}".L."Cercul circumscris"). Cerc Cerc1 = new Cerc(raza. Console.

R. Deoarece gestionarea memoriei se face automat. Destructorii sunt implementaţi prin suprascrierea acestei metode Finalize(). b = null. Pagina 25 din 52 .Read().Object este expusă: class A { } void Finalize() {} // corect În marea majoritate a cazurilor practice însă. Totuşi. Platforma . Nu trebuie să alocăm explicit memorie pentru obiecte. GC. Atunci când am terminat lucrul cu un obiect.NET SDK posedă un instrument de „făcut curat” numit “garbage collector” care caută obiectele nefolosite şi recuperează memoria ocupată de acestea. Gestionarea memoriei în C# se face dinamic şi automat.WriteLine("Destrucorul clasei B").WaitForPendingFinalizers(). Atunci când creăm un obiect nou. } } Clasa Object defineşte o metodă virtuală de finalizare prestabilită. nu este nevoie să folosim deloc metoda explicită finalize(). următorul exemplu este corect şi metoda Finalize din System.Noţiuni introductive în .Finalize(). Nu trebuie să eliberăm explicit acea zonă de memorie.L. nu este nevoie să eliberăm memoria ocupată de obiect atunci când am terminat de lucrat cu acesta. GC. Console. De aceea următorul exemplu generează două erori de compilare: class A { override protected void Finalize() {} // error public void F() { this. programatorilor C# nu le este permis să o suprascrie sau să o apeleze direct.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Curs M I. // error } } Compilatorul se comportă ca şi cum această metodă nu există de loc şi o suprascrie. C# alocă automat o zonă de memorie de dimensiunea corespunzătoare obiectului. care nu face nimic (este vidă) şi care se numeşte Finalize(). } public class ExempluDestructori { public static void Main() { B b = new B(). acesta nu mai posedă nici o referinţă activă către el (nu va mai fi atribuit nici unei variabile pe care o folosim sau nu va mai fi stocat în vreun tablou).Collect(). Astfel.NET şi C# } } class B: A { ~B() { } Console.

Pagina 26 din 52 .NET Framework. poate fi utilizat în orice alt limbaj compatibil .NET Framework Orice discuţie despre un limbaj de programare trebuie să cuprindă şi descrierea tipurilor de date pe care limbajul respectiv le pune la dispoziţia programatorilor pentru crearea de aplicaţii.String trueStr = System. În momentul execuţiei.L. Tipuri fundamentale Modelul obiectual al .1 /* Următoarele două linii de cod sunt echivalente */ System. 2. string trueStr = bool.2-3-4-5-6-7-8 © Copyright by EBS Romania S.NET Framework poate fi schiţat în felul următor: C# Tipuri fundamentale de date Common Intermediate Language (CIL) Common Type System (CTS) Virtual Object System (VOS) Common Language Runtime Tipurile fundamentale de date în C# nu sunt decât imagini ale Common Type System. astfel încât să fie permisă interoperabilitatea cross-language: un tip de dată definit în C#. Ex.TrueString.NET şi C# Tipuri de date în . deoarece sunt folosite frecvent. tipuri referinţă şi tipuri valoare. Tipuri primitive Sunt numite astfel. Compilatorul permite manipularea lor cu o sintaxă simplificată: asociază fiecărui tip primitiv tipul corespunzător descris în Base Class Library (BCL).Noţiuni introductive în . În C# există tipuri de date fundamentale şi auxiliare. În C# există trei tipuri fundamentale de date: tipuri primitive. spre exemplu. un tip de dată C# devine practic un tip din Common Type System.TrueString. Curs M I.R.Boolean.

Uint64 char System. Există două reguli importante descrise de acest model.Byte short System. System. System. clasă de bază pentru toate tipurile. Modelul obiectual al platformei . Compatibil cu standardul IEEE 754.R. Orice instanţă a acestui tip se reprezintă binar sub forma ((-296 până la 2 96) / 10 (0 până la 28)).Double Număr real cu virgulă mobilă reprezentată pe 64 biţi (precizie dublă).. Tip Tip BCL primitiv în C# sbyte System.Decimal Număr real folosit în calcule financiare (care utilizează numere mari şi care nu permit rotunjiri). Valoare minimă admisă pentru acest tip este -296 şi valoare maximă este 296. System.Object Tipul Object. MSDN Magazine. Decembrie 2000)). Număr real cu virgulă mobilă.2-3-4-5-6-7-8 © Copyright by EBS Romania S.Object. Compatibil cu standardul IEEE 754. Ex.UInt32 long System. } class MyClass : System. Număr întreg (cu semn) reprezentat pe 16 biţi. C# este limbajul reprezentativ pentru Microsoft . Număr natural reprezentat pe 64 de biţi.L.Char float System.Single double bool decimal Descriere object string Număr întreg (cu semn) reprezentat pe 8 biţi. Nu este permisă moştenirea multiplă.. Număr natural reprezentat pe 32 biţi Număr întreg (cu semn) reprezentat pe 64 de biţi.Int16 ushort System.Sbyte byte System.NET este descris de Virtual Object System (VOS). care ne interesează în acest moment: Orice obiect derivă (direct sau indirect) din tipul System.Int64 ulong System. Număr natural reprezentat pe 16 biţi. System.NET Framework şi bineînţeles că aceste reguli se aplică şi în cazul nostru. în care: Curs M I.2 // Următoarele definiţii de tipuri sunt identice class MyClass { //. Caracter Unicode reprezentat pe 16 biţi.String Tipul String Tipuri referinţă şi tipuri valoare Înţelegerea diferenţelor dintre tipurile referinţă şi tipurile valoare are o importanţă deosebită (“I believe that a developer who misunderstands the difference between reference types and value types will introduce subtle bugs and performance issues into their code” (Jeffrey Richter. reprezentată pe 32 biţi (precizie simplă).Noţiuni introductive în .NET şi C# Tipurile primitive din C# sunt prezentate în tabelul următor.Object { //. Număr întreg (cu semn) reprezentat pe 32 biţi. Pagina 27 din 52 .Int32 uint System. 2. } În C# există o ierarhie a tipurilor.UInt16 int System. Număr natural reprezentat pe 8 biţi...Boolean O valoare: True sau False System.

Un tip valoare este declarat / definit utilizând cuvintele cheie enum şi struct. enum. În figura de mai jos sunt exemplificate câteva ramuri din ierarhia de tipuri existente în C#. struct şi namespace.Form).ValueType (nod intern) System.3 using System. delegate. interface.Int32 (nod frunză) System.L.IPEndPoint (nod intern) Pentru a putea descrie tipurile referinţă şi tipurile valoare.Windows. Declaraţii / Definiţii Un tip referinţă este declarat / definit utilizând doar cuvintele cheie class.2-3-4-5-6-7-8 © Copyright by EBS Romania S. 2.NET şi C# Nodul rădăcină este System. Ex.String (nod frunză) System. Curs M I. care permite unui alt tip Y să moştenească pe X (de ex.Net. clasa System.Forms. o Fie un nod frunză al ierarhiei. care nu permite nici unui alt tip Y să îl moştenească (spre exemplu.String).Net. Pagina 28 din 52 . System. clasa System.DateTime (nod frunză) System.Object. Orice alt tip X este: o Fie un nod intern al ierarhiei. Cuvânt cheie class interface delegate enum struct namespace Descriere Defineşte un tip referinţă (clasă) Declară un tip referinţă (interfaţă) Defineşte un tip referinţă (un delegat este utilizat pentru a încapsula o metodă cu o anumită semnătură) Declară un tip valoare (enumerare) Defineşte un tip valoare (structură) Declară un domeniu de tipuri (referinţă sau valoare). Vom reveni asupra acestei figuri în paragrafele următoare. precum şi diferenţele care apar între aceste tipuri. vom analiza pe scurt următoarele cuvinte cheie din C#: class.R.EndPoint (nod intern) System. interface şi delegate.Object (rădăcina) System.Noţiuni introductive în .

} } // Declararea unui delegat public delegate void DDomeniu (). this. Console.Noţiuni introductive în . } } // Definirea unei clase class CDomeniu : ACDomeniu { public CDomeniu () { state = EDomeniu. public void Write (EDomeniu aState) { Console.L. base. // Declararea unui tip valoare enumerativ public enum EDomeniu { Working. } public override void Write () { Console. public event DDomeniu StateChanged.NET şi C# // Declararea unui domeniu de tipuri global-unice namespace Domeniu { // Declararea unei interfeţe interface IDomeniu { void Write (EDomeniu aState). } ~CDomeniu () { base.".".StateChanged (). state).WriteLine ("One CDomeniu object destroyed"). aState).StateChanged -= new DDomeniu (Write). } public static void Smth () { Curs M I.StateChanged += new DDomeniu (Write). Pagina 29 din 52 .R. public void changeInternalState () { state = EDomeniu. Sleeping } // Definirea unui tip valoare public struct SDomeniu : IDomeniu { public EDomeniu state. public abstract void Write ().WriteLine ("Internal state: {0}.WriteLine ("Received state: {0}.Sleeping.Working. } // Declararea unei clase abstracte abstract class ACDomeniu { protected EDomeniu state.2-3-4-5-6-7-8 © Copyright by EBS Romania S.

} public static void Main () { SDomeniu. acObj.NET Framewok. care gestionează lucrul cu MH în .Write ().ReadLine (). 2. SDomeniu val = new SDomeniu (). ST este stiva firului de execuţie curent. } Curs M I. MM (Memory Manager) este o componentă din Common Language Runtime (CLR).Noţiuni introductive în .. Observaţie Clasele declarate cu modificatorul abstract sunt doar parţial definite. ACDomeniu acObj = obj. Console.2-3-4-5-6-7-8 © Copyright by EBS Romania S. acObj. Console.4 // Definirea unui tip referinţă class CDomeniu : ACDomeniu { //. În principal.L. GC (Garbage Collector) este un motor apelat de MM în momentul în care se decide o acţiune de curăţare a MH. scopul acţiunii de curăţare este de a elibera din MH referinţele care nu mai pot fi accesate. IDomeniu iObj = val. Ex.state). O instanţă a unui tip referinţă este numită obiect şi o instanţă a unei structuri este numită valoare sau obiect cu tip valoare. pe care se alocă valorile.changeInternalState ().WriteLine ("*****</IDomeniu>*****"). Console. } // Definirea unui tip valoare public struct SDomeniu { //. Pagina 30 din 52 .WriteLine ("*****<CDomeniu>*****").. } } } Instanţierea tipurilor în C# Singurele tipuri care pot fi instanţiate sunt cele definite (clasele şi delegaţii – tipuri referinţă şi structurile – tipuri valoare). Creare şi stocare Vom utiliza următoarele notaţii: MH (Managed Heap) este zona de memorie (COM+) în care sunt alocate obiectele.Smth (). în sensul că ele pot fi utilizate doar ca tipuri de bază pentru alte clase.R.WriteLine ("*****<IDomeniu>*****").WriteLine ("*****</CDomeniu>*****").NET şi C# CDomeniu obj = new CDomeniu (). Console. Obiecte şi valori în C#.. iObj.. Console.Write (val. Astfel de clase nu pot fi instanţiate.

programatorul nu poate curăţa manual o zonă de memorie (nu există nici un operator dual pentru new). ci pe ST. o valoare nu este alocată pe MH. Sunt iniţializaţi membrii obiectului. Mai mult. Acest comportament nu poate fi schimbat. ceea ce implică o dimensiune a codului mai mare şi o viteză de execuţie scăzută. Discuţii legate de performanţă În general.Noţiuni introductive în . iar tipurile referinţă au un comportament orientat pe obiecte (object oriented). În exemplul de mai sus. // Instanţierea unui tip valoare: obţinem o valoare sau o variabilă de tip valoare SDomeniu val = new SDomeniu (). aşa cum s-a văzut în exemplul 3 de cod. Tipurile valoare nu oferă o interconectivitate adevărată între tipurile C#: Nu pot fi moştenite (sunt noduri frunză în ierarhia de tipuri .2-3-4-5-6-7-8 © Copyright by EBS Romania S. Spre deosebire de un obiect. Moştenesc implicit (şi definitiv) System. Oricum. obiectele trebuie eliminate din MH atunci când nu mai pot fi utilizate.Object. De fiecare dată când se utilizează o variabilă de tip valoare (vtv). System. Câteva dintre aceste situaţii sunt: 1. Operatorul new întoarce adresa la care s-a alocat un obiect. clasa care derivă direct din System. Când se utilizează new pentru instanţierea unui tip referinţă. moştenirea. cum ar fi tabela virtuală (v-table). Suplimentar. lucrul cu o variabilă de tip referinţă (vtr) implică mai întâi o dereferenţiere a unui pointer şi abia apoi lucrul efectiv cu date. Din punctul de vedere al gestionării memoriei. abstractizarea. În schimb. Un obiect este creat cu operatorul new (instrucţiunea MSIL – Microsoft Intermediate Language corespunzătoare este newobj).System. manipularea valorilor implică performanţe sporite. variabila val va conţine chiar biţii de stare ai obiectului alocat pe ST. Limitări ale tipurilor valoare Dacă lucrul cu tipuri valoare se dovedeşte a fi mai eficient. structurile pot împrumuta comportamentul specificat de o interfaţă. O instanţă a unui tip valoare se obţine fie prin new. 2.R. polimorfismul şi reutilizarea codului. Se alocă pe MH numărul de octeţi necesari pentru a reprezenta tipul obiectului. de ce să nu folosim doar astfel de tipuri? Răspunsul este că tipurile valoare au un comportament bazat pe obiecte (object based). Este posibil ca în timpul unei acţiuni de alocare.Boolean.Int32 în exemplul de mai sus). MM-ul să considere că nu există suficienţi octeţi în MH şi să apeleze GC-ul. Valorile sunt alocate pe ST şi obiectele sunt alocate pe MH. adică tot ce este mai frumos în lumea orientată obiect. Curs M I. Pagina 31 din 52 . Obiecte şi valori în C#. fie doar declarând o variabilă de acel tip. variabila obj este o adresă la biţii de stare ai obiectului proaspăt alocat pe MH. Iniţializare. ce adresează un obiect CDomeniu obj = new CDomeniu (). pot fi configuraţi anumiţi octeţi pentru componente.NET şi C# // Instanţierea unui tip referinţă: obţinem o variabilă de tip referinţă. mediul de lucru .ValueType. în sensul că nu puteţi specifica o altă clasă de bază pentru un tip valoare.NET este auto-controlat (managed). se realizează două operaţii majore: Alocare. Dar utilizarea unui tip valoare trebuie să fie întotdeauna o opţiune serioasă pentru programatori. val este numită variabila de tip valoare (vtv). Comportamentul bazat pe obiecte asigură doar parţial încapsularea.L. se accesează direct datele (biţii de stare). În exemplul de mai sus. obj poartă numele de variabilă de tip referinţă (vtr).

} public struct MyValueType : System. val2nd. // Unboxing SDomeniu val2nd = (SDomeniu) obj. Ex.6 // Cele două definiţii de tip sunt echivalente public struct MyValueType { //.Object.Noţiuni introductive în .7.L. Tip Valoare Referinţă Ex. astfel încât să se permită şi procedeul invers. 2. Deoarece doar asupra wrapper-elor se poate aplica procedeul de unboxing (sunt marcate!).6 şi 2.ValueType { //. de despachetare (unboxing).5 SDomeniu val1st = new SDomeniu ().Object După cum am menţionat anterior. } Curs M I.ValueType Această clasă este clasa de bază pentru toate tipurile valoare definite în BCL (Base Class Library) sau de programator.. 2. Mecanismul de împachetare (boxing) permite unei valori V să se comporte ca un obiect: este alocat un obiect O pe MH şi se copiază biţii de stare ai valorii în obiectul alocat.2-3-4-5-6-7-8 © Copyright by EBS Romania S.NET Framework este modul în care tipurile sunt reprezentate: împachetate (boxed) sau despachetate (unboxed). această clasă este rădăcina ierarhiei tipurilor în ...WriteLine ("Sunt egale? Raspuns: {0}". defineşte serviciile primare ale unui obiect. Clasa System. 2. în cele din urmă.. este clar că tipurile referinţă nu pot fi reprezentate în forma despachetată. } Ex. din System.Equals (val1st)).7 // Definiţia de mai jos produce o eroare de compilator: "type în interface list is not an interface" public struct MyValueType : System.NET şi C# Boxing & Unboxing O noutate în .R.. Console. Sistemul marchează pe O ca fiind un wrapper (o formă împachetată a unei valori).NET Framework. prin comportamentul specificat.Object { //. Demonstrăm acest lucru prin secvenţele de cod 2. Boxed Da Da (Nativ) Da (Nativ) Nu Unboxed System.. Orice alt tip definit de BCL (Base Class Library) sau de programator este derivat. System.Object. Pagina 32 din 52 . // Boxing object obj = val1st.

WriteLine("x = {0}. } } Output x = 110. defineşte serviciile primare ale unei valori. mC. sealed class MyClass { public int x. Din această categorie fac parte tipurile sealed şi tipurile imutabile.ValueType.NET şi C# Eroarea de compilator generată în exemplul 2. cuvânt cu cuvânt. compilatorul încă nu a evaluat tipul System.Object este o interfaţă şi adaugă acest tip în LI. Curs M I. System. Eventual.2-3-4-5-6-7-8 © Copyright by EBS Romania S.Noţiuni introductive în .y = 150. Tipuri sealed În ierarhia tipurilor .String şi System. Console. mC. dacă vor exista şi alte tipuri (separate de virgulă) după System. Mai mult. Am reuşit să ne dăm seama singuri.cs // Sealed classes using System.Object. compilatorul de C# cunoaşte faptul că tipul definit de noi moşteneşte deja clasa System.Object (“type”) nu este o interfaţă. cu unele proprietăţi specifice. aceste tipuri nu pot fi superclase pentru alte tipuri (nu pot fi derivate). Prin urmare.y). Implicit şi definitiv. compilatorul consideră că System.L. prin comportamentul specificat.x. Ex. Deoarece moştenirea multiplă nu este permisă de modelul descris de VOS. compilatorul le va adăuga în LI. de eroarea pe care am comis-o. Tipuri auxiliare Sunt tipuri valoare sau referinţă (deci nu sunt tipuri hibride).ValueType.8 // cs_sealed_keyword. până când LI va cunoaşte forma sa finală. Pagina 33 din 52 . În momentul în care încercăm să derivăm MyValueType din System. mC. compilatorul va evalua tipurile.NET Framework. În sfârşit. un tip valoare (în cazul nostru MyValueType) este derivat din System.x = 110.R.Object.ValueType. În LI (“interface list”). y = {1}". tipurile sealed reprezintă nodurile frunză. mC.Object. public int y.7 este evidentă. rezulta următorul mesaj de eroare: “'MyDerivedC' cannot inherit from sealed class 'MyBaseC'”. 2. } class MainClass { public static void Main() { MyClass mC = new MyClass().DateTime. Trebuie să recunoaştem că erorile de compilator semnalate aici sunt cu adevărat sugestive! Clasa System. Dar cum se ajunge la această eroare? 1. 3. 2. Evaluarea are loc abia după ce este construită lista de interfeţe (LI) pe care MyValueType trebuie să le implementeze. Exemple de astfel de tipuri sunt System. y = 150 Dacă în exemplul precedent se încerca moştenirea clasei MyClass prin folosirea unei instrucţiuni ca: class MyDerivedC: MyClass {} // eroare. 4.

compilatorul C# răspunde cu eroare dacă încercăm să transmitem o valoare float. Nu sunt folosite nici măcar copii ale obiectului. copiat din pt1. tipurile imutabile sunt interesante. un lucru important de înţeles îl reprezintă folosirea referinţelor.String.2-3-4-5-6-7-8 © Copyright by EBS Romania S.Noţiuni introductive în . ar fi trebuit folosite instrucţiuni new Point() separate în liniile 5 şi 6: pt1=new Point(100.Regex.Drawing. Dacă metoda creată necesită un int.Color). class TestReferinte { public static void Main(string[] arg) { SolidBrush br1.White.Red). Motivul este că în linia 6 s-a creat o referinţă de la pt2 la pt1. deoarece au comportamentul asemănător cu tipurile valoare. Pagina 34 din 52 .WriteLine("Culoare 1: " + br1. Variabilele x şi y pentru pt2 au fost şi ele schimbate. dacă încercăm să setăm o variabilă cu valoarea alteia. } } Deşi.Color=Color. trebuie să folosim variabile cu tipuri de date corespunzătoare.NET şi C# Tipuri imutabile O instanţă a unui tip imutabil (immutable) nu deţine membri care să poată să îi schimbe valoarea (mutatori).Color). la o primă vedere variabilele pt1 şi pt2 ar trebui să aibă valori diferite. de fapt se creează o noua variabilă de tipul dorit. un tip imutabil este un tip referinţă imutabil. De fapt folosim referinţe către acele obiecte.L. chiar dacă în program nu se vede nimic explicit. Pentru a înlătura acest neajuns trebuie să folosim casting-ul. Console. using System. Curs M I. Oricare dintre variabile poate fi folosită pentru a referi obiectul sau pentru a-i modifica variabilele. br1. using System. Atunci când atribuim un obiect unei variabile sau transmitem un obiect ca argument pentru o metodă nu folosim de fapt obiecte. br2=br1. Poate fi dintr-o altă clasă sau dintr-un tip de dată necorespunzător – cum ar fi float când avem nevoie de un int.100).WriteLine("Culoare 2: " + br2. Atunci când lucrăm cu obiecte.Text. valoarea variabilei nu se schimbă. La fel. pt2=new Point(100. Uneori obţinem într-un program C# o valoare care nu este de tipul necesar. Dacă am fi vrut ca pt1 şi pt2 să se refere obiecte separate. dar nu pot fi scrise ca tipuri valoare.br2. Castingul şi conversia obiectelor şi tipurilor primitive Atunci când transmitem argumente metodelor sau când folosim variabile în expresii. System. Exemple: System. ele trebuie să fie de acelaşi tip.RegularExpressions. nu este aşa. O referinţă este un tip de pointer folosit pentru a indica valoarea unui obiect. Prin urmare.100).R. Console. Folosirea referinţelor în C# devine şi mai importantă atunci când transmitem argumentele metodelor . în loc să se creeze pt2 ca un nou obiect. Pt2 este o referinţă la acelaşi obiect ca şi pt1. Casting-ul reprezintă procesul de generare a unei valori de un alt tip decât sursa. Din punctul de vedere al transmiterii parametrilor. Atunci când efectuăm un cast. br1=new SolidBrush(Color.

R. De exemplu. putem folosi o superclasă acolo unde se aşteaptă o subclasă. În majoritatea cazurilor. astfel încât valoarea să fie convertită cu uşurinţă. Castingul între tipuri primitive Cea mai des întâlnită situaţie este în cazul tipurilor numerice.). Pagina 35 din 52 . un int drept un float sau orice drept un double. Există totuşi în acest caz o problemă – deoarece subclasele au un comportament mai complex decât superclasele lor.NET şi C# Chiar dacă conceptul de casting este relativ simplu. pentru argumentul System.Forms.Windows.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Pentru a face cast pentru un obiect dintr-o altă clasă folosim aceeaşi operaţie ca şi în cazul tipurilor primitive: (numeclasa)obiect numeclasa este numele clasei destinaţie.Windows.) cât şi tipuri obiect (String. fie false şi nu pot fi folosite într-o operaţie de cast. Pentru a folosi obiecte superclasă acolo unde se aşteaptă obiecte subclasă.Forms putem transmite şi instanţe ale subclaselor sale (cum ar fi FileDialog. Nu vom pierde nici o informaţie prin cast. destinaţia poate stoca valori mai mari decât sursa.). Reciproca este şi ea adevărată. Asemănător conversiei unei valori primitive către un tip de dimensiuni mai mari. între tipuri primitive. cu o restricţie: clasele sursă şi destinaţie trebuie să fie înrudite prin moştenire. Putem transmite o instanţă a oricărei clase drept argument Object (deoarece toate clasele C# sunt subclase ale clasei Object). De multe ori putem folosi automat un byte sau un char drept un int. În multe operaţii de cast. conversia tipurilor primitive în obiecte şi apoi extragerea valorilor primitive din aceste obiecte.Noţiuni introductive în . deoarece conversia valorii poate duce la o pierdere de precizie. folosirea sa este destul de complicată de faptul că C# posedă atât tipuri primitive (int. vechiul obiect continuă să existe ca şi înainte . Există un tip de date primitiv. Trebuie să folosim un cast explicit pentru a converti o valoare mai mare într-una mai mică. unele obiecte nu au nevoie de cast explicit. Excepţia apare atunci când facem un cast de la întregi la valori în virgula mobilă – castingul unui int sau al unui long într-un float sau al unui long într-un double poate duce la pierderi ale preciziei.1 milioane. este loc mai mult decât suficient pentru a face cast de la byte la int. Reţinem că operaţia de cast creează o referinţă către vechiul obiect. iar obiect este o referinţă către obiectul sursă. nu apare nici o pierdere de informaţie.1 milioane şi 2. etc. există o pierdere de precizie. deoarece tipul de dimensiuni mai mari oferă mai multă precizie decât cel cu dimensiuni mai mici. ZipFile. Deoarece byte-ul stochează informaţii între -128 şi 127. care nu poate fi niciodată folosit pentru cast. float. Cast-urile explicite au sintaxa: (numetip)valoare numetip este numele tipului de dată către care facem conversia. valoare reprezintă o expresie care are ca rezultat valoarea tipului sursă. dar vom câştiga toate metodele şi variabilele pe care le defineşte subclasa. putem folosi un int drept un long.L. Acele obiecte superclasă s-ar putea să nu posede întregul comportament necesar pentru a putea acţiona în locul obiectului subclasă. iar un int informaţii între -2. Curs M I. OpenFileDialog). de tip numeclasa. Point etc. deoarece subclasele conţin toate informaţiile superclasei lor. Un exemplu ar fi castingul unui byte la int. etc. Există trei tipuri de cast şi de conversie despre care vom vorbi: castingul între tipuri primitive (int – float. Castingul obiectelor Instanţelor claselor li se poate aplica operaţia de cast către instanţe ale altor clase. castingul între o instanţă a unei clase şi o instanţă a altei clase. trebuie să facem cast explicit. putem folosi o instanţă a unei subclase oriunde se aşteaptă folosirea unei superclase. boolean. variabilele booleene sunt fie true. float-double. În particular. să luăm o metodă care preia două argumente: unul de tip Object şi altul de tip System. O clasă trebuie să fie subclasă a alteia.

ş. Remarcăm faptul că numele acestor clase încep cu litera mare. chiar dacă clasa obiectului nu implementează de fapt interfaţa.Parse(nume).NET Framework conţine clase care corespund fiecărui tip de date primitive: Integer. numele şi. ele determină dacă obiectele sunt de fapt acelaşi obiect. VicePresedinte este o subclasă a clasei Angajat. aceşti operatori nu realizează ceea ce ne-am aştepta.2-3-4-5-6-7-8 © Copyright by EBS Romania S. La declararea unei variabile se specifică tipul. cu informaţii suplimentare care definesc faptul că VicePresedinte are anumite drepturi suplimentare: Angajat ang=new Angajat(). Curs M I. deoarece variabila a nu a fost iniţializată.a. int c = a + b. C# tratează foarte diferit tipurile de date şi versiunile clasă ale acestora.Noţiuni introductive în . . Construcţia class Test { static void Main() { int a. Float. Pagina 36 din 52 .L. Bool.d. Castingul unui obiect către o interfaţă înseamnă că putem apela una dintre metodele interfeţei.m. ca în exemplul de mai jos: string nume="12000". int numar=Int32. programele nu se vor compila cu succes dacă se folosesc una în locul celeilalte. Conversia tipurilor primitive în obiecte şi invers Unul dintre lucrurile pe care nu le putem face în nici un caz este un cast între un obiect şi un tip de date primitiv sau invers. VicePresedinte vip=new VicePresedinte(). O conversie de care este adesea nevoie în programe este conversia unui şir într-un tip numeric. Ca alternativă. Orice variabilă trebuie să primească o valoare înainte de a se face o referire la ea. int b = 1. // e nevoie de cast explicit În afară de castingul obiectelor către clase putem de asemenea face castingul obiectelor către interfeţe – însă numai dacă clasa obiectului respectiv sau una dintre superclasele sale implementează de fapt interfaţa. Declararea variabilelor O variabilă este un spaţiu de memorare a unei informaţii. … } } // aici se generează eroare va genera o eroare. cum ar fi un întreg. ang=vip. Orice variabilă are un tip prin care se specifică ce fel de informaţii se păstrează în acea variabilă. //nu este nevoie de cast de jos in sus vip=(VicePresedinte)ang. o valoare iniţială. opţional. Compararea obiectelor Această operaţie se realizează în C# cu ajutorul operatorilor “==“ şi “!=”. În loc de a verifica dacă unul dintre obiecte are aceeaşi valoare cu celalalt obiect. Acest lucru se poate face cu metoda parseInt a clasei Integer.R. Atunci când sunt folosiţi cu obiecte. Pentru a compara instanţele unei clase şi a obţine rezultate folositoare trebuie implementate metode speciale în cadrul clasei şi apoi apelate aceste metode.NET şi C# În exemplul de mai jos putem vedea un cast de la o instanţă a clasei VicePresedinte către o instanţă a clasei Angajat. Tipurile primitive şi obiectele sunt lucruri foarte diferite în C# şi nu putem face cast automat între cele două sau să le folosim unul în locul celuilalt.

R.NET şi C# Atunci când vorbim de obiecte.ComponentModel.Container components = null.* / % & | ^ ! ~ && || true false + ++ -<< >> == != < > <= >= = += -= *= /= %= &= |= ^= <<= >>= . public bool gata = false. internal). Operatori În C# există trei tipuri de operatori: unari. protected. decrementare Deplasare Relaţionali Atribuire Acces membri Indexatori Conversie Condiţional Concatenare şi retragere “delegates” Creare obiecte Informaţii despre tip Control al excepţiilor de depăşire Adresă şi indirectare Operatori + . O variabilă este vizibilă numai în domeniul în care a fost definită! Secvenţa următoare va genera o eroare: if (i==0) {string msg = “Zero”. ne referim de fapt la variabilele asociate instanţelor claselor/structurilor sau direct claselor/structurilor (dacă este vorba de clase statice). private readonly string txtMesaj.L. binari şi operatori de conversie. O categorisire a operanzilor C# poate fi găsită în următorul tabel: Categorie operatori Aritmetici Logici şi pe biţi Concatenare Incrementare. Câteva exemple de definiţii de variabile: int y = 150. Cunoaştem că un operator returnează o valoare în urma operaţiilor asupra operanzilor. private bool y.Noţiuni introductive în . Pagina 37 din 52 . [] () ?: + new is sizeof typeof checked unchecked * -> [] & Curs M I. În declaraţia unei variabile mai poate intra specificarea unui modificator de acces (public. Ca efect secundar se poate schimba şi valoarea unora din operanzi.2-3-4-5-6-7-8 © Copyright by EBS Romania S. protected System. private.} Console.WriteLine(msg).

Câteva din namespace-urile sistem sunt: System. System. să permită dezvoltarea de componente care să fie uşor de integrat în alte aplicaţii. foreach. Namespace-ul va putea fi omis în definiţia de mai sus dacă se va specifica la începutul programului o clauză using: using Domeniu. care au funcţionalităţi în acelaşi domeniu. Clase definite în fişiere fizice diferite (assembly-uri diferite) pot face parte din acelaşi namespace.). Curs M I. Ceea ce s-a urmărit în primul rând a fost ca limbajul să fie cât mai simplu. Câteva observaţii generale despre instrucţiunile C#: instrucţiunile pot sau nu să facă parte dintr-un bloc delimitat cu {şi}.2-3-4-5-6-7-8 © Copyright by EBS Romania S. La compilare se va adăuga o referinţă la fişierul exNS. etc. Namespaces Namespace-urile (spaţii de nume) nu sunt altceva decât nişte grupări logice de componente (clase. există instrucţiunile decizionale if şi switch. Namespace-urile standard ale platformei . mai elegant şi uşor de înţeles. System. public class OClasa { // definitie clasa } } Această definiţie poate face parte dintr-un fişier. există instrucţiuni etichetate şi implicit instrucţiunea goto. o expresie poate figura ca o instrucţiune: Fct(x).Noţiuni introductive în .Data. while.dll. Declararea unei clase într-un anumit namespace se face în felul următor: namespace Domeniu { public delegate void ChangedEventHandler(string arg).R.NET sunt structurate în formă de arbore.Forms. System.dll. O aplicaţie care va avea nevoie de un obiect din clasa Oclasa îl poate declara în felul următor: private Domeniu. există instrucţiuni specifice pentru tratarea excepţiilor (try-catch-finally şi throw). dar care să fie în fişiere fizice diferite.NET.Windows. variabile. Pagina 38 din 52 . System. cum ar fi: System. // F este o funcţie de un anumit tip.Drawing. care poate fi compilat într-un DLL exNS.L. Un namespace conţine de regulă clase care pot fi grupate într-o anumită categorie. în cazul lui switch se evaluează variabile (expresii) de tip întreg sau şir. să spunem exNS. chiar dacă acestea sunt scrise în alte limbaje din familia . instrucţiunile de ciclare sunt for. do.cs. În . instrucţiunile checked şi unchecked (care pot figura şi ca operatori) permit gestionarea erorilor de depăşire de capacitate.NET există câteva namespace-uri standard.OClasa objClasa.NET şi C# Instrucţiuni în C# Majoritatea instrucţiunilor în C# sunt împrumutate din C sau C++. Reamintim că se pot defini clase în acelaşi namespace.Data.

vom crea o metodă care verifică domeniul cărţilor din bibliotecă şi pentru cele tehnice apelează o funcţie pentru care se cunosc tipul. // gestionează colecţia de cărţi public class BookDB { // Lista cărţilor ArrayList list = new ArrayList(). string author. bool technical) { list. decimal price. public decimal Price. } } // Declară tip de delegate pentru procesarea unei cărţi public delegate void ProcessBookDelegate(Book book). O implementare a acestui model este dată în continuare: // clase pentru biblioteca de carti namespace Bookstore { using System. Technical = technical. Un client care dezvoltă o aplicaţie care exploatează o astfel de bază de date îşi va crea metode proprii care prelucrează cărţile tehnice. public Book(string title. public bool Technical.Technical) processBook(b). care nu este altceva decât o adresă. price. public string Author. } // Pentru fiecare carte tehnică se apelează metoda referită de delegate public void ProcessTechnicalBooks(ProcessBookDelegate processBook) { foreach (Book b in list) { if (b. fără să se cunoască conţinutul efectiv al funcţiei. // descrierea unei carti: public struct Book { public string Title. Price = price. technical)). author.L. bool technical) { Title = title. Acest apel se face de fapt către un delegat.NET şi C# Delegaţi şi Evenimente Delegaţi Să presupunem că păstrăm evidenţa cărţilor dintr-o bibliotecă într-o bază de date şi avem colecţii. string author. // Metoda pentru adăugarea unei cărţi în baza de date: public void AddBook(string title. o referinţă la o metodă (funcţie). să spunem. Curs M I.Collections. Avantajul acestei abordări constă în aceea că în codul care menţine baza de date nu trebuie să ştim dinainte ce prelucrări se vor face cu cărţile din domeniul tehnic.R. numai cărţile din domeniul tehnic. decimal price. Author = author.Add(new Book(title. Se pune la dispoziţie o metodă care găseşte cărţile tehnice şi apelează pentru fiecare o funcţie indicată ulterior. Pentru a permite unui utilizator care utilizează baza de date să poată prelucra. clase definite pentru gestionarea acestei baze de date. parametrii şi adresa la care se găseşte. fără să îl intereseze în ce fel codul responsabil de baza de date îi selectează cărţile tehnice. Pagina 39 din 52 .Noţiuni introductive în .2-3-4-5-6-7-8 © Copyright by EBS Romania S.

ProcessTechnicalBooks(new ProcessBookDelegate(totaller. } } // Clasa pentru testarea bazei de date create class Test { // Afişeaza titlul static void PrintTitle(Book b) { Console. internal void AddBookToTotal(Book book) { countBooks += 1. priceBooks += book. // Clasa pentru calculul sumei preţurilor şi al preţului mediu class PriceTotaller { int countBooks = 0.NET şi C# } } } } Metoda ProcessTechnicalBooks primeşte ca parametru o referinţă la o funcţie care are un parametru de tip Book. În continuare dăm o secvenţă de cod client care utilizează această bază de date.0m. // Apelează o metodă care introduce cărţi în baza de date: AddBooks(bookDB).Title). b.WriteLine(" {0}". } static void Main() { BookDB bookDB = new BookDB().WriteLine("Technical Book Titles:"). decimal priceBooks = 0. } internal decimal AveragePrice() { return priceBooks / countBooks. PriceTotaller totaller = new PriceTotaller(). // Afişează cărţile tehnice: Console. Console.Noţiuni introductive în .ProcessTechnicalBooks(new ProcessBookDelegate(PrintTitle)). // Se crează o instanţă a clasei PriceTotaller pentru a obţine // preţul mediu al cărţilor tehnice.##}". Pagina 40 din 52 . // Crează un obiect delegat pentru metoda nonstatică // AddBookToTotal a obiectului totaller bookDB. Deci delegate-ul de tip ProcessBookDelegate referă o funcţie care nu returnează nimic (void) şi care are un singur parametru de tip Book. namespace BookTestClient { using Bookstore.WriteLine("Average Technical Book Price: ${0:#. Curs M I. using System.2-3-4-5-6-7-8 © Copyright by EBS Romania S.PrintTitle bookDB.L. // Crează un obiect delegat pentru metoda statică // Test.R.Price.AddBookToTotal)).

Evenimente sunt apăsarea unui buton sau taste. Să reţinem deci această proprietate foarte interesantă a delegaţilor care nu ştiu şi nu le pasă de ce tip sunt obiectele pe care le referă. etc. Obiectul care conţine evnimentul nu trebuie să ştie dinainte ce funcţie se apelează ca răspuns la acel eveniment.AddBook("The Unicode Standard 2. schimbarea poziţiei curente într-o tabelă.95m. public CuEvent() { //cod constructor } protected virtual void OnEveniment(int nr) { if (Eveniment!=null) Eveniment(null). Cu alte cuvinte. 129. În această metodă. Ritchie". Delegates reprezintă deci nişte adrese de funcţii (pointeri) asemănători cu pointerii de funcţii in C++. Delegaţii (delegates) ne spun ce fel de proceduri trebuie să scriem pentru a răspunde la un eveniment. 12.R.00m. "Ray Duncan". bookDB.Noţiuni introductive în . metodele PrintTitle şi AddBookToTotal se vor apela pentru fiecare carte din domeniul tehnic. true). după crearea şi iniţializarea unei colecţii de cărţi se apelează de două ori metoda ProcessTechnicalBooks care primeşte prima dată ca parametru un delegat pentru metoda PrintTitle. Clienţii pot lua cunoştinţă despre acel eveniment şi pot reacţiona.0". 19. true).95m. false). "The Unicode Consortium".L. class CuEvent { public event EvFunc Eveniment. } } } În această secvenţă avem o clasă PriceTotaller care conţine metode pentru calculul sumei preţurilor şi al preţului mediu. bookDB. respectiv AddBookToTotal. Pagina 41 din 52 . Astfel. Kernighan and Dennis M. Clasa test conţine metoda Main şi încă două metode statice. Exemplu: Definim un tip de delegate şi o clasă care are un eveniment tratat de un astfel de delegate: public delegate void EvFunc(int arg). Evenimente Un eveniment într-o clasă este modalitatea prin care un obiect din clasa respectivă îşi anunţă clienţii că în interiorul lui se petrece ceva.AveragePrice()).AddBook("The MS-DOS Encyclopedia". "Scott Adams". Curs M I.95m.AddBook("Dogbert's Clues for the Clueless". } // Iniţalizarea bazei de date static void AddBooks(BookDB bookDB) { bookDB. "Brian W.NET şi C# totaller. deschiderea sau închiderea unei ferestre.AddBook("The C Programming Language". bookDB.2-3-4-5-6-7-8 © Copyright by EBS Romania S. Deci noţiunea de eveniment nu are sens să fie discutată dacă nu o legăm de modalitatea în care putem reacţiona la acel eveniment. true). Ceea ce contează esta că argumentele funcţiilor invocate de delegate să corespundă cu argumentele din declaraţia delegate-ului. orice declaraţie de eveniment trebuie să fie însoţită de specificarea tipului de funcţie prin care se poate răspunde la acel eveniment. PrintTitle şi AddBooks. 39.

Nu se afişează logo-ul şi avertismentele. O linie de comandă poate arăta astfel: se compilează fişierul File.exe: csc File.cs rezultând My.2-3-4-5-6-7-8 © Copyright by EBS Romania S.exe: csc /define:DEBUG /optimize /out:File2.cs rezultând File. csc /target:library /out:File2.cs O listă a opţiunilor de compilare pe categorii este prezentă în tabelul următor: Opţiunea Optimizare /filealign /optimize Fişiere de ieşire Curs M I.exe. Compilatorul C# Compilatorul C# este csc. } private void declansare(int x) { Console. cu activarea optimizării şi generarea de simboluri pentru depanare. } } Trebuie observat că ataşarea unei funcţii la un eveniment se face cu ajutorul operatorului += urmat de cuvântul cheie new.NET şi C# } } Aceste definiţii se pot include într-o bibliotecă (DLL) care ulterior poate fi referită în orice program.cs csc /out:My.cs csc /target:library File. Pentru detaşarea unei funcţii de la un eveniment se foloseşte operatorul -= urmat de aceleaşi elemente. Activare/dezactivare optimizări. Fişierul rezultat este File2.WriteLine(”ai declansat evenimentul cu valoarea {0}”.cs se compilează File. objTest. tipul de delegate şi numele unei proceduri de tipul acestui delegate.exe File.dll: se compilează File.x). public TestEvent() { objTest = new CuEvent().dll).dll /warn:0 /nologo /debug *.exe *.Noţiuni introductive în .exe: se compilează toate fişierele C# din directorul curent rezultând un fişier cu informaţii pentru depanare (File2.cs rezultând File.Eveniment += new EvFunc(declansare). . Un program care utilizează clasa TestEvent ar arăta astfel: class TestEvent { private CuEvent objTest.cs se compilează toate fişierele C# din directorul curent.L.R. Pagina 42 din 52 Descriere Specifică dimensiunea secţiunilor în fişierul de ieşire.

Importă metadata dintr-un fişier care conţine un assembly. Include resursă în fişierul de ieşire. Referirile la fişiere vor conţine calea completă (de ex. Se definesc simboluri preprocessor (similar cu clauza #define). Specifică dacă se vor genera erori de depăşire de capacitate la rulare.Noţiuni introductive în . Pagina 43 din 52 . Se definesc simboluri preprocessor (similar cu clauza #define). Nivelul minim de la care warning-urile se afişează (0 la 4) Tratează warning-urile ca erori.2-3-4-5-6-7-8 Specifică modulele care să fie incluse în assembly-ul rezultat. Nu se vor genera warning-urile de nivelele specificate. Specifică dacă se vor genera erori de depăşire de capacitate la rulare. specificarea fişierelor care au generat erori). Nu importă biblioteca standard (mscorlib. Specifică locaţia assembly-urilor din clauza/reference. Crează fişier cu informaţii necesare pentru raportarea bug-urilor.NET şi C# Opţiunea /doc /out /target Descriere Procesează comentariile pentru documentare şi produce fişier XML Specifică numele fişierului de ieşire. Include o resursă Win32 în fişierul de ieşire. Nu se vor genera warning-urile de nivelele specificate. Include un fişier . Crează fişier cu informaţii necesare pentru raportarea bug-urilor. Se generează informaţii pentru depanare. Referiri la fişiere vor conţine calea completă (de ex.L. Se generează informaţii pentru depanare. specificarea fişierelor care au generat erori). © Copyright by EBS Romania S.ico în fişierul de ieşire. Specifică formatul fişierului de ieşire /target:exe /target:library /target:module /target:winexe Assembly-uri /addmodule /lib /nostdlib /reference Depanare şi testare erori /bugreport /checked /debug /fullpaths /nowarn /warn /warnaserror /bugreport /checked /debug /fullpaths /nowarn /warn /warnaserror /define Preprocesor /define Resurse /linkresource /resource /win32icon /win32res Curs M I.dll).R. Nivelul minim de la care warning-urile se afişează (0 la 4) Tratează warning-urile ca erori. Creează link la o resursă.

. pentru un obiect de tip Automobil putem avea proprietatea Culori. Nu se utilizează fişierul csc. Alegerea modelului de colecţie potrivit pentru implementarea unei anumite proprietăţi este o operaţiune cu care ne familiarizăm în timp. Lista tuturor opţiunilor de compilare. care va conţine toate culorile în care este disponibil automobilul respectiv.Dicţionare. Nu afişează logo-ul compilatorului.NET-ul pune la dispoziţie o gamă de colecţii care au diferite facilităţi orientate spre diferite particularităţi ale colecţiilor. De exemplu. pe măsură ce dobândim o oarecare experienţă.rsp (care conţine resurse pentru compilare). Colecţiile sunt folosite la memorarea şi manipularea datelor. Specifică codepage-ul de utilizat (dacă sau folosit mai multe codpage-uri în fişierele sursă). Colecţii de date În implementarea unui model obiectual. tabele de dispersie.Queue – listă de tip FIFO. anumite proprietăţi pot apărea sub forma unor colecţii de date. Afişează informaţiile de ieşire utilizând codificarea UTF-8. Prin colecţii vom avea acces la tipuri de date.2-3-4-5-6-7-8 © Copyright by EBS Romania S. De exemplu.NET şi C# Opţiunea Diverse @ /? /baseaddress /codepage /help /incremental /main /noconfig /nologo /recurse /unsafe /utf8output Descriere Specifică fişierul de unde se iau opţiunile de compilare şi fişierele sursă.Noţiuni introductive în . . Lista tuturor opţiunilor de compilare. . un obiect Departament al unei firme ar putea avea o proprietate Angajaţi.R. etc. care permite adăugări şi ştergeri. Accesul la valoare se realizează cu ajutorul cheii (HashTable).Stack – listă de tip LIFO.BitArray – listă de biţi (valori boolene). Sau. care este o colecţie cu toţi angajaţii din departamentul respectiv. mulţimi. valoare). precum şi la transmiterea datelor de la o metodă la alta. putem avea colecţii care să conţină obiecte de orice fel sau colecţii care conţin numai obiecte de un anumit tip. Sau putem avea colecţii în care se pot adăuga sau şterge elemente şi colecţii în care numărul de elemente este fix. Câteva din colecţiile existe în . cum ar fi vectori. Specifică în ce clasă se găseşte metoda Main. Activează compilare incrementală (numai a porţiunilor care au suferit modificări de la compilarea precedentă).ArrayList – este o listă indexată. Specifică adresa de unde se preferă încărcarea unui DLL.L. ale căror elemente sunt perechi de formă (cheie. . Compilează codul care utilizează clauza unsafe. Pagina 44 din 52 . Curs M I. . Se caută fişierele sursă în subdirectoare.NET sunt implementate de următoarele clase: .

altfel spus. Curs M I.2-3-4-5-6-7-8 © Copyright by EBS Romania S.Noţiuni introductive în . Cele mai importante interfeţe din namespace-ul Collections sunt: IEnumerable. IList şi IDictionary. În procesul de moştenire. // Fixează enumeratorul pe poziţia iniţială } Enumeratorii sunt utilizaţi doar la parcurgerea (citirea) datelor. o interfaţă defineşte metode care urmează să fie prezente în clasele derivate. în sensul că nu pot modifica datele unei colecţii. o clasă poate implementa mai multe interfeţe. ICollection. În figura următoare sunt prezentate ierarhiile în care pot fi încadrate aceste interfeţe. IDictionaryEnumerator.Collections Deja ştim că o interfaţă defineşte un anumit comportament al unei clase sau.L. IEnumerator şi IDictionaryEnumerator Un enumerator este utilizat în parcurgerea secvenţială a unei colecţii. Interfaţa de bază care descrie comportamentul unui enumerator este IEnumerator. Comportamentul unui enumerator în C# este asemănător cu cel al unui iterator în Java.R. Pagina 45 din 52 . enumeratorul este poziţionat înaintea primului element (acolo se face poziţionarea şi la apelul metodei Reset). public interface IEnumerator { object Current { get. } bool MoveNext ().NET şi C# Interfeţe în System. // Dacă mai există elemente în mulţime. avansează void Reset (). IEnumerator. La crearea unei colecţii.

Pagina 46 din 52 .Noţiuni introductive în . // Întoarce valoarea elementului curent } } Interfaţa IEnumerable IEnumerable descrie o colecţie de date ale cărei elemente pot fi enumerate (expune un enumerator pentru acea colecţie). // Număr curent de elemente } bool IsSynchronized { get. // Întoarce cheia elementului curent } object Value { get. public interface ICollection: IEnumerable { int Count { get. } ICollection ICollection descrie o colecţie de date pentru care: Elementele pot fi enumerate (comportament moştenit de la IEnumerable). public interface IEnumerable { IEnumerator GetEnumerator (). Numărul curent de elemente este cunoscut.L. public interface IDictionaryEnumerator: IEnumerator { DictionaryEntry Entry { get.NET şi C# Pentru a itera elementele unui dicţionar se utilizează enumeratori specializaţi. //Întoarce un element al dicţionarului } object Key { get. descrişi în interfaţa IDictionaryEnumerator. Elementele pot fi copiate într-un obiect de tip Array (este cunoscut numărul lor).R. // Obţin un obiect la care este asigurat accesul exclusiv } } Curs M I.2-3-4-5-6-7-8 © Copyright by EBS Romania S. // Thread-safe? } object SyncRoot { get. Se poate obţine acces exclusiv la elemente.

} object this [int index] { get. } bool IsReadOnly { get. public interface IList: IEnumerable. ICollection { bool IsFixedSize { get. bool Contains (object value). void Remove (object value). Pentru a reprezenta un astfel de element se utilizează structura DictionaryEntry. public interface IDictionary: IEnumerable.Noţiuni introductive în . "valoare" poate fi orice instanţă a unui tip referinţă. } void Add (object value). void RemoveAt (int index). object value).2-3-4-5-6-7-8 © Copyright by EBS Romania S. set. ale căror elemente sunt perechi de forma (cheie. int IndexOf (object value). } object this [object key] { get. în care: "cheie" este un obiect diferit de null. valoare).R.NET şi C# IList IList descrie colecţiile de date indexate: un element poate fi accesat prin indexul corespunzător. } ICollection Keys { get. } bool IsReadOnly { get. Pagina 47 din 52 . Curs M I. ICollection { bool IsFixedSize { get.L. set. chiar null. } IDictionary Interfaţa IDictionary este interfaţa de bază pentru toate colecţiile de tip dicţionar. void Clear (). void Insert (int index.

Vom generaliza.L. asta deoarece în momentul în care se primeşte o cheie se va şti exact în ce coş trebuie să se caute. namespace DomeniuDeTipuri { /* * Enumerez criteriile după care mulţimea de studenţi poate fi sortată. în sensul în care ar putea exista o combinaţie de date personale prin care studentul să poată fi unic determinabil (structura CheieStudent). Exemplu /* * Context: îmi inchipui un workgroup (grup de studenţi implicaţi într-o activitate . Acestea sunt tot colecţii de tip cheie-valoare.Noţiuni introductive în . într-un mod cât mai elegant.R. De asemenea.spre exemplu * Program de Consultanţă Microsoft). Alte date ar putea fi: nume. valorile hash se pot utiliza şi în verificarea integrităţii datelor (pentru date de volum mare se compară valorile hash generate la intrare cu cele generate la ieşire). Pentru fiecare cheie dintr-o pereche cheie-valoare se generează un cod unic (hash code). Aceste valori hash se utilizează şi în criptogafie. deoarece fiecare student * are o cheie unică (numărul matricol). IDictionaryEnumerator GetEnumerator ()... anul de studiu. Aceste coduri sunt adăugate în nişte coşuri. Pentru generarea unui hash code se utilizează algoritmi specifici (hashAlgorihtms). * * Cerinţă: sortarea studenţilor după diverse criterii. prin numărul matricol.Collections. */ enum SortezDupa { Curs M I. bool Contains (object key). etc..2-3-4-5-6-7-8 © Copyright by EBS Romania S.NET şi C# } ICollection Values { get. * Key: sortare după cheie (sortarea unor numere întregi aici) * Value: sortare după valoare (sortarea unor string-uri aici) * Tipul poate fi extins. } void Add (object key. O cheie hash reprezintă de fapt o secvenţă de octeţi de lungime fixă care identifică în mod unic o secvenţă voluminoasă de octeţi de dimensiune variabilă. void Clear (). } HashTable Un alt model de colecţie îl reprezintă colecţiile de tip HashTable. */ using System. * * Soluţie: mulţimea de studenţi va fi manipulată cu o tabelă de dispersie. Fiecare student poate fi identificat prin datele sale. void Remove (object key). object value). * În cazul nostru. using System. în C#. care vor restrânge ulterior setul de articole în care se face căutarea unei chei. Pagina 48 din 52 .. organizate pentru a permite căutări rapide.

nrMatricol = nrMatricol. unicitatea este dată doar de numărul matricol. */ private string nume.. } public CheieStudent (int nrMatricol) { this.R. /* * În acest caz. Curs M I. } return (codHash < altCodHash ? -1: (codHash == altCodHash ? 0: 1)).codHash = nrMatricol. Valoare struct CheieStudent: IComparable { /* * Detalii unice pentru un student: în acest caz doar numărul matricol.L. public override int GetHashCode () { return codHash. */ private int nrMatricol. Pagina 49 din 52 .ToString ().GetHashCode (). */ this. /* * Cheia studentului */ private int codHash.Noţiuni introductive în . etc.NET şi C# } Cheie.2-3-4-5-6-7-8 © Copyright by EBS Romania S. /* * Detalii student: nume. } struct Student: IComparable { /* * Cheie unică */ private CheieStudent cheie. an de studiu. } public override string ToString () { return codHash. } /* * Implementez IComparable pentru sortare (cheie). */ public int CompareTo (object altaCheieStudent) { int altCodHash = altaCheieStudent..

GetHashCode ()] = student. } /* * Nu redefini în cazul în care adaugi noi câmpuri în clasa Student! */ public override int GetHashCode () { return cheie. string nume) { cheie = new CheieStudent (nrMatricol).R.ToString ()). cheile sunt cheile studenţilor şi valorile sunt * instanţe ale tipului Student. } public void AdaugaStudent (Student student) { studenti [student. */ public int CompareTo (object altStudent) { return nume. } public void EliminaStudent (Student student) { studenti. this.Remove (student.studenti = new Hashtable (). } public Student (int nrMatricol.GetHashCode ()).Noţiuni introductive în .L. } } class WorkGroup { /* * În tabela de dispersie. */ private Hashtable studenti. } /* * Implementez IComparable pentru sortare (nume).nume = nume. Pagina 50 din 52 .CompareTo (altStudent.NET şi C# /* * Redefineşte în cazul în care adaugi noi câmpuri în clasa Student! */ public override string ToString () { return nume. * Valorile ar putea fi chiar numele studenţilor.2-3-4-5-6-7-8 © Copyright by EBS Romania S. } public void ListeazaSortat (SortezDupa criteriu) { Curs M I.GetHashCode (). dar generalizez şi aici. public WorkGroup () { this.

MoveNext () && corespEnum.MoveNext ()) { Console. wg.CreateInstance (typeof (object).Keys. " + corespEnum. 0). IEnumerator corespEnum = coresp. Curs M I. valoriTab). wg. case SortezDupa. 0).AdaugaStudent (ax). } } } public class App { public static void Main () { /* * Exemplifica */ Student dr = new Student (97107. while (tabEnum.WriteLine ( tabEnum.L.Sort (valoriTab.CopyTo (valoriTab. break. cheiTab). } } public static void Afiseaza (Array tab.Values.2-3-4-5-6-7-8 © Copyright by EBS Romania S. "Ax").ListeazaSortat (SortezDupa. wg. utilizează SyncRoot. Afiseaza (cheiTab. ICollection valori = studenti.GetEnumerator ().AdaugaStudent (gg).Current.ToString () ).Count). Array cheiTab = Array.NET şi C# /* * Pentru thread-safety. switch (criteriu) { case SortezDupa.Noţiuni introductive în . valoriTab).AdaugaStudent (dr). Array valoriTab = Array. Student ax = new Student (98007.Count).GetEnumerator (). valori.Valoare: Array. chei. * Colecţiile chei şi valori ar trebui să conţină acelaşi număr de elemente. Afiseaza (valoriTab.CreateInstance (typeof (object).Current.Cheie: Array.R. wg. Array coresp) { IEnumerator tabEnum = tab. Pagina 51 din 52 . cheiTab).Sort (cheiTab. Student gg = new Student (95782. "Gg"). */ ICollection chei = studenti.Cheie). break. valori. WorkGroup wg = new WorkGroup (). chei.ToString () + ".CopyTo (cheiTab. "Dr").

Platforma . o clasă poate fi derivată dintr-o singură superclasă. spre deosebire de cele din VB care sunt cu bază 1. aceştia se utilizează şi la ataşarea de funcţii evenimentelor. un caz particular îl reprezintă clasa HashTable. clasele definite în procesul de dezvoltare se grupează logic în namespace-uri. Delegaţii ne ajută să referim funcţii pentru care cunoaştem doar tipul parametrilor. implicit.WriteLine ("*********").Noţiuni introductive în . pentru C#. în funcţie de tipurile şi funcţionalităţile obiectelor care compun colecţiile.ReadLine (). obiectele sunt elementele create pe aceste modele cu care se operează efectiv. tipurile de date fundamentale sunt: tipurile primitive.NET Framework unifică modelul de programare pentru toate limbajele compatibile (care produc Common Intermediate Language pentru Common Language Runtime). Curs M I. } } } De reţinut… clasele reprezintă modele.NET Framework (şi implicit în C#).ListeazaSortat (SortezDupa. Pentru a accesa elementele acestor colecţii s-a creat structura DictionaryEntry. Interfaţa IEnumerator conţine funcţionalităţile de bază necesare pentru parcurgerea unei colecţii. dar poate moşteni mai multe interfeţe.2-3-4-5-6-7-8 © Copyright by EBS Romania S. tipurile referinţă şi tipurile valoare. În .NET oferă un suport larg pentru implementarea modelelor care utilizează colecţii.NET Framework şi.R. Colecţiile pot avea indecşi numerici sau indecşi cheie (de tip string).L. fără să ne intereseze exact despre ce funcţii este vorba. Colecţiile cu indexatori în C# sunt cu bază 0. wg. wg. Tipurile de date sunt sarea în bucate pentru Microsoft .Valoare). Pagina 52 din 52 . Colecţiile care conţin perechi de tip cheie-valoare sunt implementate cu ajutorul interfeţei IDictionary.EliminaStudent (ax). . interfeţele definesc un comportament comun al unor obiecte care pot fi foarte diferite.NET şi C# Console. Console. Un bun exemplu îl constituie Common Type System.

Sign up to vote on this title
UsefulNot useful