Visual C#

Lucian Sasu May 30, 2005

2

Cuprins
1 Platforma Microsoft .NET 1.1 Prezentare general˘ . . . . . . . . . . . . a 1.2 Arhitectura platformei Microsoft .NET . 1.3 Componente ale lui .NET Framework . . 1.3.1 Microsoft Intermediate Language 1.3.2 Common Language Specification 1.3.3 Common Language Runtime . . . 1.3.4 Common Type System . . . . . . 1.3.5 Metadata . . . . . . . . . . . . . 1.3.6 Assemblies . . . . . . . . . . . . . 1.3.7 Assembly cache . . . . . . . . . . 1.3.8 Garbage collection . . . . . . . . 1.4 Tr˘s˘turi ale platformei .NET . . . . . . aa 2 Tipuri predefinite, tablouri, string-uri 2.1 Vedere general˘ asupra limbajului C# a 2.2 Tipuri de date . . . . . . . . . . . . . . 2.2.1 Tipuri predefinite . . . . . . . . 2.2.2 Tipuri valoare . . . . . . . . . . 2.2.3 Tipul enumerare . . . . . . . . 2.3 Tablouri . . . . . . . . . . . . . . . . . 2.3.1 Tablouri unidimensionale . . . . 2.3.2 Tablouri multidimensionale . . 2.4 Siruri de caractere . . . . . . . . . . . ¸ 2.4.1 Expresii regulate . . . . . . . . 3 Clase, instructiuni, spatii de ¸ ¸ 3.1 Clase – vedere general˘ . . a 3.2 Transmiterea de parametri 3.3 Conversii . . . . . . . . . . 3.3.1 Conversii implicite nume . . . . . . . . . . . . . . . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 11 12 12 12 13 14 15 16 17 17 17 21 21 23 24 25 29 36 36 37 41 43 45 45 49 55 55

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

4 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.3.10 3.3.11 3.3.12 3.3.13 Spatii ¸ 3.4.1 3.4.2 Conversiile implicite ale expresiilor constante Conversii explicite . . . . . . . . . . . . . . Boxing ¸i unboxing . . . . . . . . . . . . . . s Declaratii de variabile ¸i constante . . . . . ¸ s Declaratii de etichete . . . . . . . . . . . . . ¸ Instructiuni de selectie . . . . . . . . . . . . ¸ ¸ Instructiuni de ciclare . . . . . . . . . . . . ¸ Instructiuni de salt . . . . . . . . . . . . . . ¸ Instructiunile try, throw, catch, finally . . . ¸ Instructiunile checked ¸i unchecked . . . . . ¸ s Instructiunea lock . . . . . . . . . . . . . . . ¸ Instructiunea using . . . . . . . . . . . . . . ¸ de nume . . . . . . . . . . . . . . . . . . . . Declaratii de spatii de nume . . . . . . . . . ¸ ¸ Directiva using . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CUPRINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 57 60 62 62 63 64 66 66 67 67 67 68 69 70 75 75 76 77 77 77 78 78 79 79 80 81 81 81 87 92 93 95 95 96 99 99 101

3.4

4 Clase 4.1 Declararea unei clase . . . . . . . 4.2 Membrii unei clase . . . . . . . . 4.3 Cˆmpuri . . . . . . . . . . . . . . a 4.3.1 Cˆmpuri instante . . . . . a ¸ 4.3.2 Cˆmpuri statice . . . . . . a 4.3.3 Cˆmpuri readonly . . . . . a 4.3.4 Cˆmpuri volatile . . . . . a 4.3.5 Initializarea cˆmpurilor . . ¸ a 4.4 Constante . . . . . . . . . . . . . 4.5 Metode . . . . . . . . . . . . . . . 4.5.1 Metode statice ¸i nestatice s 4.5.2 Metode externe . . . . . . 4.6 Propriet˘¸i . . . . . . . . . . . . . at 4.7 Indexatori . . . . . . . . . . . . . 4.8 Operatori . . . . . . . . . . . . . 4.8.1 Operatori unari . . . . . . 4.8.2 Operatori binari . . . . . . 4.8.3 Operatori de conversie . . 4.8.4 Exemplu: clasa Fraction . 4.9 Constructori de instant˘ . . . . . ¸a 4.10 Constructori statici . . . . . . . . 4.11 Clase interioare . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

CUPRINS 5 Destructori. POO ˆ C# ın 5.1 Destructori . . . . . . . . . . . . . . . . . . . . . . . 5.2 Specializarea ¸i generalizarea . . . . . . . . . . . . . . s 5.2.1 Specificarea mo¸tenirii . . . . . . . . . . . . . s 5.2.2 Apelul constructorilor din clasa de baz˘ . . . a 5.2.3 Operatorii is ¸i as . . . . . . . . . . . . . . . s 5.3 Clase sealed . . . . . . . . . . . . . . . . . . . . . . . 5.4 Polimorfismul . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Polimorfismul parametric . . . . . . . . . . . . 5.4.2 Polimorfismul ad–hoc . . . . . . . . . . . . . . 5.4.3 Polimorfismul de mo¸tenire . . . . . . . . . . . s 5.4.4 Virtual ¸i override . . . . . . . . . . . . . . . s 5.4.5 Modificatorul new pentru metode . . . . . . . 5.4.6 Metode sealed . . . . . . . . . . . . . . . . . . 5.4.7 Exemplu folosind virtual, new, override, sealed 5.5 Clase ¸i metode abstracte . . . . . . . . . . . . . . . s 5.6 Interfete . . . . . . . . . . . . . . . . . . . . . . . . . ¸ 5.6.1 Clase abstracte sau interfete? . . . . . . . . . ¸

5 105 . 105 . 107 . 107 . 108 . 110 . 110 . 111 . 111 . 111 . 111 . 113 . 114 . 116 . 117 . 119 . 120 . 126 127 . 127 . . . . . . . . . 128 131 132 135 135 135 142 142 146

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

6 Delegati. Evenimente. Structuri ¸ 6.1 Tipul delegat . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 Utilizarea delegatilor pentru a specifica metode la run¸ time . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2 Delegati statici . . . . . . . . . . . . . . . . . . . . . ¸ 6.1.3 Multicasting . . . . . . . . . . . . . . . . . . . . . . . 6.2 Evenimente . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Publicarea ¸i subscrierea . . . . . . . . . . . . . . . . s 6.2.2 Evenimente ¸i delegati . . . . . . . . . . . . . . . . . s ¸ 6.2.3 Comentarii . . . . . . . . . . . . . . . . . . . . . . . 6.3 Structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.1 Structuri sau clase? . . . . . . . . . . . . . . . . . . . 7 Tratarea exceptiilor. Atribute ¸ 7.1 Tratarea exceptiilor . . . . . . . . . . . . . . . ¸ 7.1.1 Tipul Exception . . . . . . . . . . . . . 7.1.2 Aruncarea ¸i prinderea exceptiilor . . . s ¸ 7.1.3 Reˆ ıncercarea codului . . . . . . . . . . 7.1.4 Compararea tehnicilor de manipulare a 7.1.5 Sugestie pentru lucrul cu exceptiile . . ¸ 7.2 Atribute . . . . . . . . . . . . . . . . . . . . . 7.2.1 Generalit˘¸i . . . . . . . . . . . . . . . at . . . . . . . . . . . . . . . . . . . . erorilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

147 . 147 . 147 . 148 . 159 . 161 . 162 . 163 . 163

. . . . . . . . . . . . . .2 Metode . . . .1 Obiecte DataAdapter . .4 Utilizarea de seturi de date multiple . . at 9. .1 Propriet˘¸i . . . . . . . . . . . . . . .2. . . . . . . .4. . . . . . . . . . . . .5. . . . . . . . .6. . . . 199 . . . . . . . . . . . . . . . . . . . . . . .6. . . . .4 Obiecte Connection . . 9. . . . . . .1 Ce reprezint˘ ADO.3 Evenimente . .2 Clasa DataSet . . ¸ 9. 176 8. . . . . .5. . . 173 a 8. . . . . . 180 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Folosirea comenzilor parametrizate . .NET . . 188 s 8. . . . . . 188 8. .1 Propriet˘¸i . . . . . . . . . . . . . .6. . 9. . . . . . 196 . . . . . . . . .2. . .3. . . . . . .3. . . . . . . 182 8. . 170 8 ADO. . . 164 Exemplificarea altor atribute predefinite . . . . . . . . . . .5. . . . . . . . . . . . . .3 Crearea ¸i utilizarea unui DataReader . . . . . . 199 . . 185 a a 8. . . . . . . . . . . . 176 8. .4 CUPRINS Atribute predefinite . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Atribute definite de utilizator . . . . . . . . . . . . . . . . . . . . . . 9.3 7. 179 8. . . . . .2 Metode . . . . .2 Metode . . . . . . 179 8.3 Utilizarea unei comenzi cu o procedur˘ stocat˘ . . . . . . .1 Continut . 187 8. . . . .3. . . . . . . . .NET? . . . . . 176 8. . . . . . . . . . . . . .3.2 7. . . .2 Furnizori de date ˆ ADO. . . . . 9. . . . 195 . . .4 Stocarea stringului de conexiune ˆ fi¸ier de configurare 179 ın s 8. . . . . .5 Accesarea datelor ˆ ıntr–o manier˘ sigur˘ din punct de a a vedere a tipului . . . . .3 Relatii ˆ ¸ ıntre tabele . . . . . . . . . 176 8. . . . . .4 Clasele DataAdapter . . . . . .4.3. . . . . . . . . . . 177 at 8. .4. . . . . 174 8. . 193 . . . . 175 8. . . . . . . . . . . . . . . . . . . . . . . . . . .5 Gruparea conexiunilor . 185 8. . . . . .5 Obiecte Command . . . . .5. .3 Componentele unui furnizor de date . . . . . . .NET (2) 9. . . . . . . 181 8. . 194 . . . . . . . . . 181 at 8. . . . . . . . . . . . . . . . . . . .2. . . . 187 at 8. .4 Popularea unui DataSet . . . 193 . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . 196 . . 174 ın 8. . . . . . . . . . . .6. . . . . . .1. . .2. . . . . . . . . . . . . . .2 Clasa DataTable . . .1 Propriet˘¸i . . . . . . . . .2 Clasele Command .6. . . . . . . . .NET 173 8. . . . . . . . . . . . . .5 Clasa DataSet . . . . .6 Obiecte DataReader . . .3 Clasele DataReader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 8. . . .4. . . . . . . . . . . . . . 176 8.2 Propriet˘¸i . . . . . .6 7. . . . .2. . . . . . . . 190 9 ADO.1 Clasele Connection . . . . . . . . . . . . . .1.1 Metode . 195 . . . .2. . . .2. . . . . . . . 9. . . . . . . . .

11. . . . . . . . . 234 . . .1. . 213 . . . .1. . . . . .5.1.2 Clasa Page . . . .3 Suspendarea firelor de executie . 231 . . 225 . . . . 10. . . . . . . .NET folosind Visual Studio. . . . . . . . . . .5. . . . . . . . 11. . . . . . . . . . . . . . . . . . . .4. . . . . . 209 . . . .NET 11. . . . . . . . . . . .1 Label . . . . . . .5. . . . . . . . . . . . . . . . . . . . 11.NET . .1 Anatomia unei pagini ASP. . . . 11. . . . . . . . . . . . . . . . .5 Propagarea modific˘rilor c˘tre baza de date . . . . 229 . . . . . . . . .5 CheckBox . 226 . .1 Managementul thread–urilor . .5. . . . . . .2 Instructiunea lock .2 Sincronizarea . . . . . . . .NET (2) 237 12. 228 .NET .2 Ad˘ugarea scriptului inline . . . . . . . . . . 209 . . . .3 Clasa Monitor . 11. . . . . . . . . . . . . . .4 Controale server . 234 . . . . .2 Data Binding . . . . . . . . . . . 218 . .3 Evenimentul Unload . . . . . . . . . . . . . .1 Evenimentul Init . . . . . . .2. 235 . . . . . . . . . . . . . 238 . 11. . . . . . . . . . . .6 RadioButton . . . . 10.5 Sugerarea priorit˘¸ilor firelor de executie at ¸ 10. 11. . . . . . . . .1 Postback . . . .2. . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . .4 TextBox . . . . 11. . . . . . . . . .1 Controale de validare . . . . . . . .2. .5. .1. . a 11. . . . 233 .1. .2 Evenimentul Load . 237 12. . .3 9. . . . . . . . . 10.CUPRINS 7 9. . . . . . . . . . . . . . . . . . . . . . . 217 . . . 205 . . . . . . . . 235 . . . .1 Ad˘ugarea unui control Web . . . . . . . . . . . . . . . ın s ın 10. . . . .3 LinkButton . 10. . . . 215 . . . . . . . . 11. . . . .2. 205 . .1. . 200 a a Tranzactii ˆ ADO. . . . . . . . . . . . a 11. . . . 11. . . . . . . .2. 11. . . . . . . . . . . . . 202 ¸ ın . . . . . . . . . . . . . .5 Controale Web . 228 . . . . . . . . . . . . . . . . 233 . . 229 . a 10. . . . . 10. . . . . .NET 11. . 213 . . . . . . .1 Pornirea thread–urilor . . . . . . . . . . . . ¸ 10. . . . . . . .6 Fire ˆ fundal ¸i fire ˆ prim-plan . . .1. . . . 224 . .2. . . .1. . . . . . . 11. . 231 . . . . . . . . . . . 11. . . . .2. . . . . . . . . . . . . . . . . . 224 . . . . . .1. . .3 Code-behind . .1.1 RequiredFieldValidator . . . . . . 12 ASP. . . . . . . . . . .4. . . . . . . . . . . 235 10 Fire de executie ¸ 10. . 205 . 235 . . . . . 235 . . . . 11.4 Omorˆrea thread–urilor . . . . . 11. 219 223 . . 11 ASP. . . . . . . . . . . . . . .7 DropDownList . . .5. . . 208 . . . . . . . . . . . . .1 Clasa Interlocked .2 Button . . . . . . . . . . . ¸ 10. . . . . . . .3 Crearea unei pagini ASP. . . .2 Metoda Join() . 11. . . . . . . . . . . . . . 228 .

. . . . . . . . .2 Elementul body . . . . . . s ¸ Fi¸ierul global.1 Componentele unui WS . 251 . . . . . . .1 Generarea programatic˘ continutului a ¸ 12.2. . . . . . . . . . . . . . . a 13. . . . . . . . . . 248 . . .5 12. . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Crearea unui serviciu Web simplu . . . .2 Schema de codificare . . . .8 13 Servicii Web 13. . . . . . Fi¸ierul de configurare al aplicatiei Web . . . . . 13. .2 Discutii asupra blocurilor componente .1. . 256 . .3 Conventia de formatare . . . . . . . . . at 13. . 12. . .4 12. .6 ValidationSummary . 248 . . . .1. . .3 SW pentru transmitere de continut binar ¸ 13. .2 Redirectarea .3. . . .1 Generalit˘¸i . . . . . 12. . . 249 . . . . 13. . . .2 Validarea unui num˘r de card de credit . . . . . . . . . . . . . . . Alte puncte de interes ˆ aplicatii ASP. . .7. . . . . . 251 .NET ın ¸ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . .2 12. . . . . . . . . . . . . . . .1 Adunarea a dou˘ numere . . . .2. . . . . . 247 . . .2. . . . . . 253 . . .4 CompareValidator . . . . . . .1. . . . . . . . .5 Mecanisme de descoperire . . . . . . . 238 238 238 239 240 240 241 241 242 243 243 244 245 245 245 12. . . . . . . . ViewState . . . . . . . . . . . . . . . . . . . . . . .1. . . . 247 . . . . . .3 RangeValidator . . . . . 12. . .4. . . . . . . . . . . . . . . . .2. . . . . 255 . . . . . . . . . .asax . . a 13. . . . . . . . . . . .2. . . . . .6 12. .4 SOAP . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . 250 . . . . 12. . .8 12. .4 Mecanismul de descriere . 12. . . . . . . . . . . . . 13. . . . . 13. . . . . . .7 12. . . . . . . . . . . ¸ 13. . . 254 . . . 13. . 252 .2. 247 . . . . . . . . . . . . . . . . CUPRINS . . . . . . s Managementul sesiunii . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . Comunicarea cu browserul . ¸ 13. .1 Application . . . . . 248 . . . . . . . . Cookies . . . . .2 RegularExpressionValidator . . . . . . 250 . . .3 12. . .1. . . . . .5 CustomValidator . . . 13. . . . . . .1 Protocolul de transport .1 Header-e . . . . . . . . . .1. . . . . . . . .4. . 13. . . .

aplicatii ¸ ¸ WEB si servicii WEB.asp ¸ a Serviciilor Web . XML). Fortran. martie 2005.NET 1. etc). Eiffel. o bibliotec˘ cuprinz˘toare de clase pentru crearea serviciilor Web (Web Sera a 2 vices) . Ea const˘ ˆ trei p˘rti principale: Common Language a ın a¸ Runtime. sub care se vor realiza. infrastructura . J#. Servere specializate .NET. de asemenea integreaz˘ tehnologii care au fost lansate de a catre Microsoft incepˆnd cu mijlocul anilor 90 (COM. Python. clase pentru platform˘ ¸i ASP. www. Objective-C. Smalltalk. continuatoare ale lui SQL Server 2000.NET.un set de limbaje (C#. Lisp. pentru a asigura portabilitatea codului. BizTalk 2000. s . aplicatiilor Web (Web Forms) ¸i aplicatiilor Windows (Win¸ s ¸ dows Forms).Curs 1 Platforma Microsoft . O infrastructur˘ ajut˘toare.NET Framework.NET Compact Framework este un set de interfete de programare ¸ care permite dezvoltatorilor realizarea de aplicatii pentru dispozitive mobile ¸ precum telefoane inteligente ¸i PDA-uri1 . Visual Basic . etc.un set de servere Enterprise .microsoft. etc) a sau tehnologii actuale (servicii Web. DCOM. Exchange 2000.NET este un nou cadru de dezvoltare a softului.NET. ActiveX.NET. Platforma const˘ cˆteva grupe de produse: a a 1.aplicatii care ofer˘ servicii folosind Web-ul ca modalitate de acces.com/net/basics/glossary. Managed C++. un set de medii de dezvoltare (Visual Studio . as a a Microsoft . Pascal. 2. ¸ a 9 . Cobol.NET Framework constituie un nivel de abstractizare ˆ ıntre aplicatie ¸i ¸ s kernel-ul sistemului de operare (sau alte programe).1 Prezentare general˘ a Platforma . Visio). Unelte de dezvoltare . RPG. Haskell. distribui si rula aplicatiile de tip forme Windows. care pun la 1 2 Definitia oficial˘ Microsoft. Perl.

NET Compact Framework. Bussiness to Bussiness .Comert electronic ˆ ¸ ıntre parteneri de afaceri.NET este de a oferi toate acestea. Dezvoltarea orientat˘ pe componente . s 3 . Aplicatiile distribuite .noi dispozitive non–PC.NET Framework: Pocket PC Phone a Edition. Tablet PC. email. Modific˘ri ale paradigmei Web . Dispozitive . programabile prin .sunt din ce ˆ ce mai numeroase aplicatiile de ¸ ın ¸ tip client / server sau cele pe mai multe nivele (n−tier). Smart Display.NET pune la dispozitie un mod mai simplu de a dezvolta ¸i ¸ s a distribui componente.de-a lungul timpului s–au adus ˆ a ımbun˘t˘¸iri tehnologiilor Web pentru a simplifica dezvoltarea aplicatiilor.un mod prin care utilizatorii se pot autentifica pe site-urile Web vizitate. accentuˆndu–se urm˘toarele directii: a a ¸ 1. ¸ 3. a at ¸ ˆ ultimii ani. De¸i nu este omiprezent. set-top boxes. a dar dezvoltarea ¸i distribuirea aplicatiilor COM este prea complex˘. 4. a a a ın dispozitive inteligente ¸i servicii conlucreaz˘ pentru atingerea scopurilor s a propuse. Servicii Web . scalabilitate.este de mult timp cerut˘ sima a plificarea integr˘rii componentelor software dezvoltate de diferiti proa ¸ duc˘tori. etc. unul din dezideratele .reprezint˘ con¸tienti¸ a s zarea cererilor de interoperabilitate. Viziunea actual˘ s a ¸a a a a se dep˘rteaz˘ de cea de tip client/server c˘tre una ˆ care calculatoare. dezvoltarea aplicatiilor Web s–a mutat de la prezentare In ¸ (HTML ¸i adiacente) c˘tre capacitate sporit˘ de programare (XML ¸i s a a s SOAP). Motivul pentru care Microsoft a trecut la dezvoltarea acestei platforme este maturizarea industriei software. s ¸ a Microsoft . folosind un singur nume ¸i o parol˘ pentru toate. 3. Alti factori de maturizare a industriei software . COM (Component Object Model) a realizat acest deziderat. ¸ ¸ at 3 aplicatii B2B . disponibilitate. Toate acestea se fac deja folosind standarde Internet neproprietare (HTTP. multe s a s site-uri ˆ folosesc pentru a u¸ura accesul utilizatorilor.NET dispozitie functionalit˘¸i diverse pentru stocarea bazelor de date. Smartphone. Tehnologiile distribuite actuale cer de multe ori o mare afinitate fat˘ de produc˘tor ¸a a ¸i prezint˘ o carent˘ acut˘ a interoper˘rii cu Web-ul.10 CURS 1. PLATFORMA MICROSOFT . XML. SOAP).NET Passport . diferit˘ de a comertul electronic ˆ ¸ ıntre client ¸i afacere (Bussiness to Consumer – B2C). o versiune redus˘ a lui . 2. XBox.cel mai notabil exemplu este . ıl s 4.

lucrul cu ¸iruri de caractere.NET Framework . precum operatii de I/O.NET este compilat ˆ Microsoft Interın mediate Language (MSIL).1.NET. Base Class Library exist˘ pen¸ a a tru a asigura functionalitate de nivel sc˘zut. Aceste limbaje sunt sprijinite de o bogat˘ colectie de biblioteci a ¸ de clase. La baza tuturor se afl˘ cea mai impora ¸ a tant˘ component˘ a lui . a a care r˘spunde de executia fiec˘rui program. Mediul de dezvoltare Visual a ¸ a Studio .2.NET 11 1. ˆ concordant˘ cu Common Language Specificaın ¸a tion (CLS). Comunicarea dintre aplicatii ¸i servicii se s ¸ s face pe baza unor clase de manipulare XML ¸i a datelor.1 schematizeaz˘ arhitectura platformei Microsoft . etc. ce pun la dispozitie facilit˘¸i pentru dezvoltarea de Web Forms.2 Arhitectura platformei Microsoft .Common Language Runtime. Aceste ¸ s ¸ ¸ clase sunt reunite sub numele de .1: Arhitectura . Orice a program scris ˆ ıntr-unul din limbajele . dar datorit˘ extensibilit˘¸ii este cel mai a at .NET Figura 1. ¸ at Windows Forms ¸i Web Services.NET nu este absolut necesar pentru a dezvolta aplicatii (exist˘ ¸i ¸ a s alternative open-source pentru el). comunicatie prin retea. ceea ce sprijin˘ s a dezvoltarea aplicatiilor cu arhitectur˘ n-tier. ce permite dezvoltarea rapid˘ a aplicatiilor. ARHITECTURA PLATFORMEI MICROSOFT . fire de ¸ a ¸ executie.NET Figura 1.NET Framework Class Library.

a a IL are tr˘s˘turi OO. se pot s a ¸ a a a modifica toate detaliile interne.NET Framework Microsoft Intermediate Language Una din uneltele de care dispune ingineria software este abstractizarea. etc). f˘r˘ a afecta actiunile celorlati beneficiari ai aa ¸ ¸ codului. Dar limbajele nu ¸ 4 www. Deseori vrem s˘ ferim utilizatorul de detalii. Dac˘ interfata r˘mˆne neschimbat˘. Managed C++.NET nu este exclusiv a dezvoltat˘ pentru sistemul de operare Microsoft Windows.3 1. s˘ punem la dispozitia altora a a ¸ o interfat˘ simpl˘. sau IL pe scurt). indiferent de platforma ¸int˘. Trebuie spus c˘ platforma . polimorfisaa s mul. De remarcat c˘ aceast˘ abstractizare de limbaj permite a a rularea aplicatiilor independent de platform˘ (cu aceea¸i conditie ca la Java: ¸ a s ¸ s˘ existe o ma¸in˘ virtual˘ pentru acea platform˘). nivelul inferior este rezer¸ vat sistemului de operare. ˆ cazul limbajelor de programare. ci ¸i pentru arome a s 4 de Unix (FreeBSD sau Linux . care s˘ permit˘ atingerea scopului.com . a a a s ın Microsoft a realizat ¸i el propria sa abstractizare de limbaj. capabil˘ s˘ “traduc˘” mai departe fi¸ierul class ˆ cod nativ.2 Common Language Specification Unul din scopurile . Evident. este cod scris ˆ s a ıntrun limbaj intermediar care suport˘ POO. precum p-code (cel produs de compilatorul Pascal-P) ¸i bytecode (binecunoscut celor care au lucrat ˆ Java). de¸i scrise ˆ diferite limbaje. s-a ajuns treptat la crearea unor nivele In de abstractizare a codului rezultat la compilare. mo¸tenirea. precum exceptiile ¸ sau evenimentele. De¸i exist˘ mai multe limbaje s a de programare de nivel ˆ ınalt (C#. a s a a a 1. Visual Basic . polimorfismul.1 Componente ale lui .go-mono.NET bine adaptat pentru crearea aplicatiilor. Bytecod-ul este ˆ acela¸i timp o a ın s abstractizare care permite executarea codului Java. precum abstractizarea datelor.3. la compilare toate vor produce cod ˆ acela¸i limbaj intermediar: Microsoft ın s Intermediate Language (MSIL. aceasta nus mindu-se Common Intermediate Language. folosind din plin s ın mo¸tenirea. s ın Bytecode-ul Java. PLATFORMA MICROSOFT . atˆta timp cˆt aceast˘ platform˘ are implementat˘ o ma¸in˘ virtual˘ t a a a a a a s a a Java. pot interopera.a se vedea proiectul Mono ). exceptiile. ˆ s ıncapsularea.NET este de a sprijini integrarea limbajelor astfel ˆ at ıncˆ programele. generat prin compilarea unui fi¸ier surs˘. etc. 1.NET.3. Asem˘n˘tor cu bytecod-ul. sau concepte care s-au dovedit a fi extrem de necesare. f˘r˘ a fi necesare ¸a a a a aa cunoa¸terea tuturor detaliilor.12 CURS 1.

Obiectele ¸i tipurile create ˆ diferite limbaje pot interactiona f˘r˘ a s ın ¸ aa probleme suplimentare.NET a a Framework. s ın Microsoft a publicat Common Language Specification (CLS). ın 1.NET PE). Codul translatat este depus ˆ a a ın s a ıntr-un cache.3 Common Language Runtime CLR este de departe cea mai important˘ parte component˘ a lui .NET.NET (. ci un executabil portabil . vezi 1. ci se va rula de c˘tre CLR. Acest cod nu este deci un executabil nativ. disponibilizeaz˘ memoria prin garbage collection. cu CLR–ul — vezi mai jos) ˆ ıntr-un mod independent de limbajul surs˘. evitˆnd-se astfel recompilarea ulterioar˘.compileaz˘ ˆ a ıntregul cod ˆ cod nativ singur˘ dat˘. a ˆ urma compil˘rii unei aplicatii rezult˘ un fi¸ier cu extensia exe. este tradus˘ ˆ cod ma¸in˘. ˆ s a s a a ın care o metod˘ sau o functie. ın . Combinatia CTS/CLS realizeaz˘ de fapt interoper¸ a area limbajelor. ın CLR instantiaz˘ obiectele. CLS define¸te un set de reguli pentru compilatoarele . altele nu (Visual Basic .NET FRAMEWORK 13 sunt identice: unele suport˘ supraˆ arcarea operatorilor (Managed C++. dar In a ¸ a s care nu este un executabil portabil Windows. continˆnd specificatii de reguli ¸ a ¸ necesare pentru integrarea limbajelor. este foarte similar cu Java Virtual Machine.1.3. unele sunt case sensitive. Este responsabil cu managementul ¸i executia codului scris ˆ s ¸ ın limbaje .3.NET. se poate ca o clas˘ scris˘ ˆ C# s˘ fie mo¸tenit˘ a a ın a s a de o clas˘ scris˘ ˆ Visual Basic care arunc˘ exceptii ce sunt prinse de cod a a ın a ¸ scris ˆ C++ sau J#. Normal JIT . eliberˆnd resursele folosite de codul nativ ce este a stocat ˆ cache. Exist˘ 3 tipuri de compilatoare a a a JIT: 1. ˆ a ıntocmai cum un fi¸ier class este rulat ˆ cadrul JVM. Pentru a se asigua totu¸i interoperabilitatea codului scris ˆ diferite limbaje. ˆ mod ın a a In normal este folosit la instal˘ri. Econo-JIT . 2. a ınc˘ C#). un subset al lui CTS (Common Type System. face verific˘ri de securitate. Concret. asigurˆnd s a faptul c˘ fiecare compilator va genera cod care interfereaz˘ cu platforma a a (mai exact. ˆ momentul ˆ care este apelat˘ pentru prima a ¸ ın ın a oar˘.a se vedea descrierea de mai sus. CLR s ın folose¸te tehnologia compil˘rii JIT .o implementare de ma¸in˘ virtual˘. Pre-JIT .se folo¸e¸te pe dispozitive cu resurse limitate. Compileaz˘ s s a codul IL bit cu bit. aflat ˆ format IL. a 3.NET). depune obiectele ˆ ¸ a a ın memorie.4).3. COMPONENTE ALE LUI . altele nu.

3. dac˘ ma¸ina virtual˘ este bine adaptat˘ la noua platform˘. Transferul parametrilor se face s rapid.NET ˆ esent˘. s a reducˆnd overhead-ul cerut de mecanismul de garbage collection. Boxing ¸i unboxing . o dat˘ ce a fost compilat. ca alternativ˘ la compilarea repetat˘ a aceleia¸i buc˘¸i ¸ ¸ a a s at de cod ˆ cazul unor apel˘ri multiple. De exemplu: s .NET trebuie s˘ aibe un set a comun de concepte pentru a putea fi integrate.ˆ general. acest mecan¸a ın ism se nume¸te boxing. a 2. f˘r˘ a mai fi nevoie a aa recompilarea lui (precum ˆ C++. Toate limbajele care fac parte din pleiada .NET este acela¸i ca ¸i ˆ Java: performanta. o clas˘ scris˘ ˆ C# trebuie s˘ fie echivalent˘ cu una scris˘ ˆ VB. se execut˘ pe diverse ın ın a a procesoare. structuri ¸i enumer˘ri. a as a a s O scurt˘ descriere a unor facilit˘¸i comune (ce vor fi exhaustiv enumerate a at ¸i tratate ˆ cadrul prezent˘rii limbajului C#): s ın a 1. o a a ın a a a ın interfat˘ scris˘ ˆ Managed C++ trebuie s˘ fie perfect utilizabil˘ ˆ Managed ¸a a ın a a ın Cobol. activitatea unui compilator JIT este destinat˘ a ˆ In ¸a a ımbun˘t˘¸i pera at formanta executiei. r˘d˘cina ierarhiei existente ˆ . vezi mai jos) suport˘ dou˘ tipuri diferite: tipuri ¸ a a valoare ¸i tipuri referint˘. de exemplu).Int32. se manipuleaza eficient.14 CURS 1. CLR-ul (care se ocup˘ de managementul ¸i ın a s executia codului IL. orice ın s limbaj trebuie s˘ recunoasc˘ ¸i s˘ poat˘ manipula ni¸te tipuri comune.NET Framework.motivul pentru care exist˘ tipuri primitive este s a ˆ a orice variabil˘ ˆ . Modul ˆ care acest deziderat ın s-a transformat ˆ realitate se nume¸te Common Type System (CTS). dar referintele induc un cost suplimentar datorit˘ mecanismului ¸ a de garbage collection. PLATFORMA MICROSOFT . Tipurile valoare se stocheaz˘ pe stiv˘.4 Common Type System Pentru a asigura interoperabilitatea limbajelor din . Unul din avantajele mecanismului JIT ın a apare ˆ clipa ˆ care codul. Variabilele de tip referinta contin ¸˘ ¸ adrese de memorie heap ¸i pot fi null.NET.3. int este un alias pentru System.NET. Tipurile valoare includ tipuas rile primitive. Tipuri referint˘ . ın 1.ValueType. atunci a s a a a acest cod va beneficia de toate optimiz˘rile posibile. dar pot fi a a oricˆnd convertite ˆ a ıntr-un tip referint˘ memorat ˆ heap. Datorit˘ faptului c˘ de regul˘ s a a a a au dimensiuni mici ¸i sunt alocate pe stiv˘. Tipurile valoare reprezint˘ tipuri alocate s ¸a a pe stiv˘ ¸i nu pot avea valoare de null.se folosesc dac˘ variabilele de un anumit tip cer ¸a a resurse de memorie semnificative. De a a a ın exemplu. care se deriveaz˘ din a System. Ins˘ s s ın ¸ a ın compatibil˘ cu clasa Object. Tipuri valoare .

5 Metadata Metadata ˆ ınseamn˘ ˆ general “date despre date”. assemblies.NET Framework: metadata. sau interfetele Java. vizibilitate.NET suport˘ pe deplin proat a gramarea orientat˘ pe obiecte. f˘cˆndu–se abstractie de originea lui. ˆ cazul . Pe baza metadatei. polimorfismul) sau tr˘s˘turi legate de clase (metode. Delegati . accesibilitate. ce permit programarea ¸ ¸ ¸ generic˘. De asemenea se includ tr˘s˘turi precum propriet˘¸i. indexatori . propriet˘¸i. cˆms aa a puri. garbage collection. eveniaa at mente.inspirati de pointerii la functii din C. etc). se obtine un obiect care poate fi gestionat la fel a ¸ ca oricare altul.platforma . Se permite implementarea simultan˘ a mai ¸ a multor interfete (ˆ rest mo¸tenirea claselor este simpl˘).reprezint˘ acela¸i concept precum clasele abstracte din C++ ¸ a s (dar continˆnd doar functii virtuale pure). membri statici.3. unde operatorul de conversie este suficient pentru a converti de la un obiect la o variabil˘ de tip valoare. a ıl CLR ¸tie cum s˘ instantieze obiectele. nu de utilizatorul a ¸ a s a uman. Interfete . indexatori. ca mai jos: ın int j = (int)box. a a ¸ Inversa boxing-ului este unboxing-ul. ea a ın In reprezint˘ informatii destinate a fi citite de c˘tre ma¸in˘. o aplicatie (nu at ¸ . Printr-un mecanism numit reflection. O ¸ a ¸ ¸ clas˘ care se deriveaz˘ dintr-o interfat˘ trebuie s˘ implementeze toate a a ¸a a metodele acelei interfete. Reprezint˘ versiunea “sigur˘” a pointerilor c˘tre functii din a a a a ¸ C/C++ ¸i sunt mecanismul prin care se trateaz˘ evenimentele. //box . mo¸tenirea. assembly cache. 1. prin care se poate converti un obiect ˆ tipul valoare echivalent. cum s˘ s a ¸ a a acceseze propriet˘¸ile.NET FRAMEWORK int i = 1. //i . a reflection. cum s˘ le apeleze metodele.un obiect referinta 15 Cˆnd se face boxing.NET.3. ¸ ın s a 6.un tip valoare object box = i. Este stocat˘ ˆ a ımpreun˘ cu codul pe care ˆ descrie. 5. Clase. tipuri interioare. concepte legate de obiecte (ˆ a ıncapsularea. s a Exist˘ numeroase componente ale lui CLR care ˆ fac cea mai impora ıl tant˘ parte a lui . a 4.1. COMPONENTE ALE LUI .

Scopul acestor “assemblies” este a s˘ se asigure dezvoltarea softului ˆ mod “plug-and-play”. Sunt folosite de asemenea ¸ ın ¸i referintele c˘tre orice assembly extern de care are nevoie aplicatia. ea nu este folosit˘ de c˘tre sistemul de operare. Ulterior. reutilizare ¸i pera a s misiuni de securitate. ¸ ¸ referiri la alte assemblies. un tip de date exist˘ ˆ interiorul unui a ın assembly (¸i nu poate exista ˆ exteriorul acestuia). metadata contine o declaratie a fiec˘rui tip ¸i cˆte o declaratie ¸ ¸ a s a ¸ pentru fiecare metod˘. neap˘rˆnd a ¸ a ¸ a aa ˆ manifestul unui assembly daca acesta nu a fost gˆndit ca o aplicatie parın a ¸ tajat˘. s ¸ a ¸ Versionarea este un aspect deosebit de important pentru a se evita a¸a– s numitul “DLL Hell”. Dar metadatele a ın nu sunt suficiente pentru acest lucru. Cˆnd se dore¸te rua a ın ¸ a s larea unei aplicatii continute ˆ assembly. PLATFORMA MICROSOFT . Mai pe larg. informatia despre versiune. instalarea lui poate fi ¸ ıl f˘cut˘ copiind assemblyul ˆ directorul destinatie dorit. Scenariile precedente erau de tipul: se instaleaza o aplicatie care aduce ni¸te fi¸iere . permisiuni de secua ın ritate ¸i altele. dar cu care vechea aplicatie nu mai functioneaz˘ a ¸ ¸ a corespunz˘tor.NET. cˆmp. ın a a . Mecanismul a ın ¸a prin care aceste informatii se folosesc pe parcursul rul˘rii de c˘tre aplicatii ¸ a a ¸ se nume¸te reflection. versionare. De¸i fi¸ierele dll contin informatie relativ ¸ ¸ s s ¸ ¸ la versiune ˆ interiorul lor. o ¸ s s alt˘ aplicatie care se instaleaz˘ suprascrie aceste fi¸iere (sau m˘car unul din a ¸ a s a ele) cu o versiune mai nou˘. Reinstalarea vechii aplicatii nu rezolv˘ problema.dll necesare pentru functionare. De asemena ınc˘ a a mai poate contine declaratii despre cultura aplicatiei respective. maniferstul va instrui mediul . Contine numele assembly-ului. s Un manifest reprezint˘ metadate despre assembly-ul care g˘zduie¸te tia a s purile de date.6 Assemblies Un assembly reprezint˘ un bloc functional al unei aplicatii . o list˘ a tipurilor ˆ assembly. El a ¸ ¸ formeaz˘ unitatea fundamental˘ de distribuire. proprietate.NET neap˘rat CLR) poate s˘ interogheze aceast˘ metadat˘ ¸i s˘ afle ce expune a a a as a un obiect. s 1. Un assembly contine s ın ¸ metadate care sunt folosite de c˘tre CLR.16 CURS 1. eveniment al tipului respectiv. mai sunt necesare ¸i “manifestele”. Aceast˘ informatie care este unic˘ este optional˘.3. metadata contine informatie care pera a ¸ ¸ mite ˆ arc˘torului clasei respective s˘ localizeze corpul metodei. a Deoarece un assembly contine date care ˆ descriu. adic˘ despre ¸ ¸ ¸ a localizarea ei (limba folosit˘ ˆ partea de interfat˘ utilizator). a a Pentru fiecare metod˘ implementat˘. s Un assembly care este ˆ artit ˆ ımp˘ ¸ ıntre mai multe aplicatii are de asemenea ¸ un shared name. deoarece a ¸ a a doua aplicatie nu va functiona. La runtime.NET ¸ ¸ ın despre modulele care sunt continute ˆ assembly.

el va fi a s a ad˘ugat ˆ assembly cache.4. programatorul poate cere rularea lui.3.NET 17 ceea ce duce la probleme. Atunci cˆnd un assembly este instalat pe o ma¸in˘. Este un mod de rezolvare a proba a lemei “DLL Hell”. TRASATURI ALE PLATFORMEI . Garbage collection este mecanismul care se declan¸eaz˘ s a atunci cˆnd alocatorul de memorie r˘spunde negativ la o cerere de alocare de a a memorie. ad˘ugˆnd doar noul assembly. Aplicatiile a a ¸ instalate vor avea assemblies ˆ ıntr-un assembly cache global.4 Tr˘s˘turi ale platformei . Dac˘ un assembly este desc˘rcat de pe Internet.3. Implementarea este de tip “mark and sweep”: se presupune initial ¸ c˘ toat˘ memoria alocat˘ se poate disponibiliza.8 Garbage collection Managementul memoriei este una din sarcinile cele mai consumatoare de resurse umane.7 Assembly cache Assembly cache este un director aflat ˆ mod normal ˆ directorul \Winnt ın ın \Assemblies. dar ˆ acest mod ar disp˘rea reutilizarea acestor ın ¸ ın a biblioteci. Totu¸i. va evita suprascrierea a assembly-urilor deja existente (¸i care functioneaz˘ perfect cu acplicatiile s ¸ a ¸ instalate). cele care nu mai sunt ¸ referite sunt dealocate. Dac˘ programul de instalare este scris corect. 1. ˆ ın ıntr-o zon˘ tranzient˘. celelalte zone de memorie sunt compactate.NET a a Prin prisma celor prezentate pˆna acum putem rezuma urm˘toarele tr˘a a a s˘turi: a . CLR este cel care decide. pe baza informatiilor din manifest.˘ ˘ 1. s ¸a 1. dupa care se determin˘ a a a a care din obiecte sunt referite de variabilele aplicatiei. unde suprascrierea unei biblioteci dinamice cu o variant˘ a mai nou˘ putea duce la nefunctionarea corespunz˘toare a aplicatiilor antea ¸ a ¸ rior instalate. ¸ care este versiunea corect˘ de assembly de care o aplicatie are nevoie. la dorint˘. Acest a ¸ mecanism pune cap˘t unei epoci de trist˘ amintire pentru programatori ¸i a a s utilizatori. pentru a nu cre¸te semnificativ penalizarea de performant˘. a ın a a el va fi stocat ˆ acest assembly cache. CLR este cel care se ocup˘ de apelarea mecanismului de In a garbage collection. 1. ˆ acest assembly cache vor exista versiuni multiple ale aceluia¸i assemIn s bly. s ¸a ˆ general. O solutie la aceast˘ dilem˘ ar fi instalarea fi¸ierelor ¸ a a s dll ˆ directorul aplicatiei. Obiectele a c˘ror dimensiune de memorie este mai mare decˆt un anumit prag nu mai a a sunt mutate.

a a a a Datorit˘ CLR-ului. alegerea lor fiind f˘cut˘ pe baza manifestelor. versionarea este acum un aspect de care se ¸ine cont. Numarul limbajelor curent implementate este mai mare decˆt 10.18 CURS 1. ¸ ın • Independenta de procesor ¸i de platform˘: IL este independent ¸ s a de procesor. foarte asem˘n˘tor cu HTTP5 . fiind a implementat ˆ sisteme mult mai timpurii. ın • Suportul pentru versionare: Ca o lectie ˆ a¸at˘ din perioada de ¸ ınv˘t a “DLL Hell”.NET. aplicatia este izolat˘ de particularit˘¸ile hardware a ¸ a at sau ale sistemului de operare. s • Distribuirea u¸oar˘: Actualmente instalarea unei aplicatii sub Wins a ¸ dows ˆ ınseamn˘ copierea unor fi¸iere ˆ ni¸te directoare anume. SOAP. Aceast˘ dezvoltare are ˆ vedere ¸i debugging-ul a a ın s aplicatiilor dezvoltate ˆ mai multe limbaje. iar dezinstalarea aplicatiei s˘ se fac˘ prin ¸tergerea acelui director. t Dac˘ o aplicatie a fost dezvoltat˘ ¸i testat˘ folosind anumite compoa ¸ as a nente. moa s ın s dificarea unor valori ˆ regi¸tri. bazat pe text. datorit˘ metadatelor ¸i reflect˘rii trec de ¸ a s a aceste probleme. spre deosebire de DCOM sau CORBA. ¸ a a s • Arhitectur˘ distribuit˘: Noua filosofie este de a asigura accesul la a a servicii Web distribuite. orice aplicatie .NET • Dezvoltarea multilimbaj: Deoarece exist˘ mai multe limbaje pentru a aceast˘ platform˘. overhead-ul ina dus de c˘tre mecanismul de garbage collection este suportabil. acestea conlucreaz˘ la obtinerea informatiei a ¸ ¸ 5 Folosit la transmiterea paginilor Web pe Internet . PLATFORMA MICROSOFT . ın s Dezinstalarea complet˘ a unei aplicatii este in majoritatea cazurilor a ¸ o utopie. s a a • Sprijinirea standardelor deschise: Nu toate dispozitivele ruleaz˘ a sisteme de operare Microsoft sau folosesc procesoare Intel. el poate a a trece u¸or de firewall-uri. Aplicatiile . etc. Deoarece SOAP este un protocol simplu. • Managementul automat al memoriei: Problemele de tipul memory leakage nu mai trebuie s˘ preocupe programatorii. O dat˘ scris˘ ¸i compilat˘. instalarea unei componente de versiune mai nou˘ nu va atenta la a buna functionare a aplicatiei ˆ discutie: cele dou˘ versiuni vor coexista ¸ ¸ ın ¸ a pa¸nic. este mai u¸or de implementat p˘rti specifice ˆ lima a s a¸ ın bajele cele mai adecvate. Din aceast˘ a cauz˘ orice este strˆns legat de acestea este evitat.NET (al c˘rei a as a ¸ a management este f˘cut de c˘tre CLR) poate fi rulat˘ pe orice platform˘. Se folose¸te XML ¸i a a s s cel mai vizibil descendent al acestuia. Se dore¸te ca instalarea unei aplicatii s˘ nu ˆ s ¸ a ınsemne mai mult decˆt copierea fi¸ierelor necesare ˆ a s ıntr-un director. instalare de componente COM.

ex. sau folosirea de c˘tre o component˘ COM a unei componente a a . ¸ • Interoperabilitate cu codul “unmanaged”: Codul “unmanaged” se refer˘ la cod care nu se afl˘ ˆ totalitate sub controlul CLR. Platforma . intranet.NET de un control mai fin. ma¸ina local˘. pe baza metadatelor din assembly (zona din care provine . etc) precum ¸i s a s a politicilor de securitate ce se pot seta. . El a a ın este rulat de CLR. folosirea componentelor ¸ COM. sau cel din Java. TRASATURI ALE PLATFORMEI . ˆ care codul suspectat este ın rulat ˆ ıntr-un “sandbox”.4. bazat˘ pe drepturile a a contului utilizatorului. a Este vorba de apelurile functiilor din DLL-uri. dar nu beneficiaz˘ de CTS sau garbage collection. f˘r˘ acces la resursele critice este ˆ aa ınlocuit ˆ ın .˘ ˘ 1.NET. Internet. Modalitatea actual˘ de securizare. ın • Securitate: Aplicatiile bazate pe componente distribuite cer automat ¸ securitate. Codul existent se poate folosi ˆ continuare.NET 19 dorite.NET asigur˘ suport ¸i unelte pentru realizarea acesa s tui tip de aplicatii.

20 CURS 1. PLATFORMA MICROSOFT .NET .

un spatiu de ın ¸ ¸ nume este o colectie de tipuri sau o grupare de alte spatii de nume care pot ¸ ¸ 1 2 “#” se pronunt˘ “sharp” ¸a Eng: namespace 21 . Tipuri predefinite. este o directiv˘ care specific˘ faptul c˘ se vor a a a 2 folosi clasele care sunt incluse ˆ spatiul de nume System. motiv pentru care curba de ˆ a¸are este a a s ınv˘t foarte lin˘. Tablouri. este: ıntˆ ın using System. Este foarte asem˘n˘tor cu Java ¸i C++. } } Prima linie using System. Siruri de ¸ caractere 2.WriteLine(‘‘Hello world!’’). simplu.Curs 2 Vedere general˘ asupra a limbajului C#.1 Vedere general˘ asupra limbajului C# a C#1 este un limbaj de programare modern. class HelloWorld { public static void Main() { Console. a Un prim exemplu de program. care contine o serie de elemente ce se vor ¸ ˆ alni ˆ continuare. obiect–orientat.

Constructia “{0}” va fi ˆ ¸ ınlocuit˘ cu primul a argument care urmeaz˘ dup˘ “Hello {0}”. La executarea programului de a a mai sus ˆ forma: HelloWorld Ana Dan. care s˘ fie folosit˘ a a a de c˘tre sistemul de operare pentru a semnala dac˘ procesul s–a ˆ a a ıncheiat cu succes sau nu3 . i++) { Console. TABLOURI. Mention˘m faptul c˘ limbajul este case–sensitive4 . se va afi¸a pe ecran: ın s Hello Ana Hello Dan Metoda Main poate s˘ returneze o valoare ˆ a ıntreag˘. se folose¸te clasa Console ¸ s s din spatiul de nume System. a ¸ orice program este continut ˆ ¸ ıntr–o clas˘. a O variant˘ u¸or modificat˘ a programului de mai sus. dup˘ care face trecerea la linie s a a nou˘.WriteLine( ‘‘Hello {0}’’. } } } ˆ exemplul de mai sus metoda principal˘ preia o list˘ de parametri In a a transmi¸i din linia de comand˘ (un ¸ir de obiecte de tip String) ¸i va afi¸a s a s s s pentru fiecare nume “Hello” urmat de numele de indice i (numerotarea parametrilor ˆ ıncepe de la 0). Punctul a ın de intrare ˆ aplicatie este metoda Main. ˆ care se salut˘ a s a ın a persoanele ale c˘ror nume este transmis prin linia de comand˘: a a using System. ˆ cazul nostru HelloWorld. pentru aceast˘ clas˘ se apeleaz˘ metoda static˘ ¸ a a a a WriteLine. i<args. ˆ cazul de fat˘. ¸ a a Ca metode de notare Microsoft recomand˘ folosirea urm˘toarelor dou˘ a a a conventii: ¸ 3 4 De exemplu ˆ fi¸iere de comenzi prin testarea variabilei de mediu ERRORLEVEL ın s Face distinctie ˆ ¸ ıntre litere mari ¸i mici s . Mai departe. STRING-URI fi folosite ˆ ıntr-un program (detalii vor fi date mai tˆrziu). care nu preia ˆ acest exemplu nici ın ¸ ın un argument din linia de comand˘ ¸i nu returneaz˘ explicit un indicator de as a stare a termin˘rii. a In ¸a clasa care este folosit˘ din acest spatiu de nume este Console. TIPURI PREDEFINITE. a Pentru operatiile de intrare–ie¸ire cu consola.Length. care afi¸eaz˘ pe ecran mesajul. args[i]).22 CURS 2. class HelloWorld { public static void Main( String[] args) { for( int i=0.

Se recomand˘ evitarea folosirii ¸ a a a notatiei ungare (numele unei entit˘¸i trebuie s˘ se refere la semantica ei.2.2 Tipuri de date C# prezint˘ dou˘ tipuri de date: tipuri valoare ¸i tipuri referint˘. ¸ at a nu la tipul de reprezentare). TIPURI DE DATE 23 • Conventie Pascal. propriet˘¸i.1: ın Tabelul 2. metode. float) . char. etc.1: Cuvinte cheie ˆ C# ın abstract case const do explicit float implicit is null params ref sizeof this uint using base catch continue double extern for in lock object private return static throw ulong virtual bool char decimal else false foreach int long operator protected sbyte string true unchecked void break checked default enum finally goto interface namespace out public sealed struct try unsafe while byte class delegate event fixed if internal new override readonly short switch typeof ushort 2.2. a a ˆ general. dar primul caracter al ¸ a a primului cuvˆnt nu este scris ca liter˘ mare. Cuvintele cheie (cuvinte rezervate care nu pot fi folosite ca ¸i identificas tori) din C# sunt date ˆ tabelul 2. tipurile enumerare 5 De fapt acestea sunt structuri. int. conventia tip Pascal este folosit˘ pentru tot ce este vizibil din exIn ¸ a teriorul unei clase. prezentate ˆ alt curs ın . ˆ care prima liter˘ a fiec˘rui cuvˆnt se scrie ca liter˘ ın a a a a mare • conventia tip ”c˘mil˘” este la fel ca precedenta. Doar parametrii at metodelor se scriu cu conventia c˘mil˘. precum clase. Tipua a s ¸a 5 rile valoare includ tipurile simple (ex.

STRING-URI ¸i structur˘ ¸i au ca principale caracteristici faptul c˘ ele contin direct datele s as a ¸ referite ¸i sunt alocate pe stiv˘ sau inline ˆ s a ıntr–un struct. Demn de rea a ¸ a marcat este c˘ toate tipurile de date sunt derivate (direct sau nu) din tipul a System.2.Object. delegat ¸i tablou. el punˆnd la dispozitie ın a a a ¸ 28 de cifre zecimale semnificative. toate avˆnd proprietatea a ¸a s a c˘ variabilele de acest tip stocheaz˘ referinte c˘tre obiecte. Tipul string este folosit pentru manipularea ¸irurilor de caractere s s codificate Unicode. la care orice tip a a (inclusiv un tip valoare) poate fi convertit. TABLOURI.1 Tipuri predefinite C# contine un set de tipuri predefinite. s Tipul char este folosit pentru a reprezenta caractere Unicode. TIPURI PREDEFINITE. int val = 12. pe 16 biti ¸ tip ˆ ıntreg cu semn. tipurile ¸ ˆ ıntregi cu semn ¸i f˘r˘ semn. punˆnd astfel la dispozitie un mod unitar de tratare a lor. long val1 = 12. pe 64 biti ¸ tip ˆ ıntreg f˘r˘ semn. ar˘tˆnd totodat˘ ¸ aa a cum se scriu valorile corespunz˘toare: a Tabelul 2.engl. reprezentate pe 16 biti. tipurile bool s aa ın a a ¸i decimal. Tipul decimal este folosit pentru calcule ˆ care erorile determinate ¸ ın de reprezentarea ˆ virgul˘ mobil˘ sunt inacceptabile. uint val = 12. pe 8 biti aa ¸ tip ˆ ıntreg f˘r˘ semn. 6 Spunem despre un string c˘ este invariabil . continutul obiectelor de tip string nu se poate modi¸ 6 fica . pentru care nu este necesar˘ in¸ a cluderea vreunui spatiu de nume via directiva using: string. interfat˘. Tipul bool este folosit pentru a reprezenta valorile logice true ¸i false. pe 32 biti aa ¸ Exemplu object a = null. string s = “hello”. byte val = 12. immutable a . object. Tabelul de mai jos contine lista tipurilor predefinite. tipuri numerice ˆ virgul˘ mobil˘.24 CURS 2. sbyte val = 12. long val2=34L. short val = 12. Tipurile referint˘ ¸a includ tipurile clas˘. ushort val = 12. pe 8 biti ¸ tip ˆ ıntreg cu semn.2: Tipuri predefinite. Tip object string sbyte short int long byte ushort uint Descriere r˘dacina oric˘rui tip a a o secvent˘ de caractere Unicode ¸a tip ˆ ıntreg cu semn. a ¸ 2. pe 16 biti ¸ tip ˆ ıntreg cu semn.NET. Clasa object este r˘d˘cina ierarhiei de clase din . pe 16 biti aa ¸ tip ˆ ıntreg f˘r˘ semn.

simpl˘ precizie a a a float val=1. char tip caracter din setul Unicode char val=’h’. operatori. fie boolean. ¸ a 7 Engl: integral type . int este alias pentru System. Tipurile numerice sunt tipuri ˆ ıntregi. TIPURI DE DATE Tabelul 2. uint. ˆ virgul˘ mobil˘ sau decimal. dubl˘ precizie ın a a a double val1=1. fie enumer˘ri. ın a a Tipurile intregi sunt sbyte. decimal tip zecimal cu 28 de cifre semnificative decimal val=1. Un tip simplu este fie de tip numeric7 . Vor fi descrise ˆ ˆ ın ıntr–o sectiune urm˘toare. propriet˘¸i. int. string este alias pentru clasa System. char.23M. cˆmpuri. double tip ˆ virgul˘ mobil˘. indexatori. O variabil˘ de tip valoare a a ˆ ıntotdeauna trebuie s˘ contin˘ o valoare (nu poate fi null.2 (continuare) Tip Descriere Exemplu ulong tip ˆ ıntreg f˘r˘ semn.2 Tipuri valoare C# pune programatorului la dispozitie tipuri valoare. ın Structuri Un tip structur˘ este un tip valoare care poate s˘ contin˘ declaratii de a a ¸ a ¸ constante. Atribuirea pentru un astfel de tip ˆ ¸a ınseamn˘ copierea a valorii (clonarea) dintr–o parte ˆ alta. constructori a at sau tipuri imbricate. Nu este a posibil ca dintr–un tip valoare s˘ se deriveze.Int32. bool val2=true.String. care sunt fie struc¸ turi. bool tip boolean bool val1=false. Exist˘ un set predefinit de structuri numite tipuri simple.4=76UL. ulong val2=34U. cele ˆ virgul˘ mobil˘ sunt float ¸i double.2. 2. ulong. a a identificate prin cuvinte rezervate. ushort.23F. ulong val3=56L. care la rˆndul a a ei este derivat˘ din clasa object (alias pentru System. double val2=4. metode.56D. pe 64 de biti aa ¸ ulong val1=12.Object). De exemplu.ValueType. Tipurile enumerare se pot defini ın a a s de c˘tre utilizator. float tip cu virgul˘ mobil˘.2. byte. a Toate tipurile valoare deriveaz˘ din clasa System. 25 Fiecare din tipurile predefinite este un alias pentru un tip pus la dispozitie ¸ de sistem. spre deosebire a ¸ a de tipurile referint˘). ulong va.23. short.2. long.

long. //metoda System. De exemplu.MaxValue. //idem //double d = Double.Int64 ulong System.Int32. STRING-URI Tipuri simple C# pune are predefinit un set de tipuri structuri.ParseDouble("3. ushort. Acestea au urm˘toarele dimensiuni ¸i domeniu de valori: s a s • sbyte reprezint˘ tip cu semn pe 8 biti. ulong ¸i char.Int32. short.3 Cuvˆnt rezervat Tipul alias a sbyte System.ToString(). Tipurile simple sunt identificate prin cuvinte rezervate.UInt16 int System. //constanta System.26 CURS 2.Single double System.MaxValue string s = i. tipul int. int.ToString().SByte byte System. dar acestea reprezint˘ a doar alias–uri pentru tipurile struct corespunz˘toare din spatiul de nume a ¸ System.ToString() string t = 3. cu valori de la -128 la 127. a ¸ . numite tipuri simple. corespondenta este dat˘ ˆ tabelul de mai jos: ¸ a ın Tabelul 2.Int16 ushort System.Char float System.Byte short System.14"). TABLOURI.Decimal Deoarece un tip simplu este un alias pentru un tip struct.Double bool System.UInt64 char System. Tipuri ˆ ıntregi C# suport˘ nou˘ tipuri ˆ a a ıntregi: sbyte. fiind un tip alias pentru System. urm˘toarele declaratii sunt legale: a ¸ int i = int. TIPURI PREDEFINITE.Int32.3: Tipuri simple ¸i corespondentele lor cu tis ¸ purile din spatiul de nume System. ¸ Tabelul 2. uint.Int32 uint System. orice tip simplu are membri.Boolean decimal System. byte.UInt32 long System.

backslash ¸i new line. De¸i ca reprezentare. Regulile dup˘ ın a care se asigneaz˘ un tip pentru o valoare sunt: a 1. s 27 • char reprezint˘ tip f˘r˘ semn pe 16 biti. uint. char este identic cu ushort. \a. \b. Dac˘ o valoare este ˆ afara domeniului lui ulong. UL.2. ˆ a ¸ ıntre −263 ¸i 263 − 1. ˆ a ¸ ıntre -32768 ¸i 32767. O secvent˘ escape hexazecimal˘ ˆ ¸a a ıncepe cu \x urmat de 1–4 cifre hexa. a ¸ a a 2. In ¸a a exceptˆnd apostrof.2. uL. Literalii de tip caracter au forma: ‘car’ unde car poate fi exprimat printr– un caracter. Lu. s • short reprezint˘ tip cu semn pe 16 biti. TIPURI DE DATE • byte reprezint˘ tip f˘r˘ semn pe 8 biti. dac˘ ¸irul de cifre are sufixul ul. atunci el este considerat ca fiind a s primul tip care poate s˘ contin˘ valoarea dat˘: int. nu toate operatiile ce de s ¸ pot efectua cu ushort sunt valabile ¸i pentru char. \". Secvent˘ escape simpl˘ poate fi: a s ¸a a \’. el este considerat ca fiind din as primul tip care poate s˘ contin˘ valoarea dat˘: uint. ulong. el este a s considerat ca fiind din tipul ulong. Reprezentarea unei variable de tip ˆ ıntreg se poate face sub form˘ de ¸ir a s de cifre zecimale sau hexazecimale. s • ushort reprezint˘ tip f˘r˘ semn pe 16 biti. ˆ a aa ¸ ıntre 0 ¸i 255. LU. ˆ a aa ¸ ıntre 0 ¸i 65535. s • int reprezint˘ tip cu semn pe 32 de biti. ˆ a ¸ ıntre −231 ¸i 231 − 1. \n. urmate eventual de un prefix. Numerele exprimate ˆ hexazecimal sunt prefixate cu “0x” sau “0X”. \r. ulong. cu valori ˆ a aa ¸ ıntre 0 ¸i 65535. secvent˘ escape hexazecimal˘ ¸a a ¸a a ˆ prima form˘ poate fi folosit orice caracter sau secvent˘ escape Unicode. s • long reprezint˘ tip cu semn pe 64 de biti. lu. s . dac˘ ¸irul de cifre are sufixul u sau U. printr–o secvent˘ escape simpl˘. ˆ a aa ¸ ıntre 0 ¸i 232 − 1. dac˘ ¸irul de cifre are sufixul l sau L. \t. ˆ a aa ¸ ıntre 0 ¸i 264 − 1. \0. cu semnificatiile cunoscute din ¸ C++. el este considerat ca fiind din a s primul tip care poate s˘ contin˘ valoarea dat˘: long. Ul. lU. \\. a ¸ a a 4. dac˘ ¸irul de cifre nu are un sufix. \f. long. \v. apare o eroare la coma ın pilare. s Multimea valorilor posibile pentru char corespunde setului de caractere ¸ Unicode. s • uint reprezint˘ tip f˘r˘ semn pe 32 de biti. ulong. s • ulong reprezint˘ tip f˘r˘ semn pe 64 de biti. a ¸ a a 3.

de exemplu 0/0 sau −1).0 × 10−324 ¸i s 308 1. . Operatiile cu floating point nu duc niciodat˘ la aparitia de exceptii. precum ¸ ın a a ¸i un set finit de numere8 . +. .//se va arunca exceptie System. dar anumite operatii duc la obtinerea acestor a ¸ ¸ dou˘ valori).7 × 10 cu o precizie de 15-16 cifre. nu se semnaleaza eroare checked { i=255. *. ¸ Exemplu: byte i=255.4 × 10 (¸i din domeniul negativ corespunz˘tor). TABLOURI. Double poate reprezenta valori cuprinse ˆ ıntre 5.OverflowException. a valorii Not–a–Number (NaN) (obtinut˘ ¸ a √ prin operatii ˆ virgul˘ mobil˘ invalide. }//i va avea valoarea 0. iar bitii semnificativi care nu mai ˆ as a ¸ ıncap ˆ ın reprezentare sunt eliminati.(unar ¸i bi¸ s nar). care permit reprezentarea valorilor de “0 pozitiv” ¸i “0 s negativ” (se comport˘ la fel. ˆ caz de operatii invalide. ın ¸ 8 Pentru detalii vezi [4].OverflowException } Pentru expresiile aritmetice care contin operatorii ++. infinit sau NaN. o eroare de dep˘¸ire duce la arunın as ˆ context unchecked. cu o pres s a cizie de 7 cifre. respectiv strict negativ la 0). +∞ ¸i −∞ (obtinute prin ˆ artirea unui num˘r strict pozia s ¸ ımp˘ ¸ a tiv. unchecked { i++. Tipul float poate reprezenta valori cuprinse ˆ s ıntre −45 38 1. i++. carea unei exceptii de tip System. comportamentul depinde de utilizarea operaın ¸ torilor sau a declaratiilor checked ¸i unchecked (care se pot utiliza ˆ surs˘ sau ¸ s ın a din linia de compilare): ˆ context checked. a Tipuri ˆ virgul˘ mobil˘ ın a a Sunt prezente 2 tipuri numerice ˆ virgul˘ mobil˘: float ¸i double. . s ¸ ın comportamentul este specificat prin intermediul optiunii /checked[+|−] dat ¸ din linia de comand˘ pentru compilator.-. la valori 0. respectivi 64 de biti. TIPURI PREDEFINITE. STRING-URI ˆ cazul ˆ care o operatie aritmetic˘ produce un rezultat care nu poate fi In ın ¸ a reprezentat ˆ tipul destinatie. Tipuın a a s rile sunt reprezentate folosind precizie de 32. 93.28 CURS 2. dar ¸ a ¸ ¸ ele pot duce.5 × 10 ¸i 3. pag. folosind ¸ formatul IEC 60559. / ¸i care nu sunt continute ˆ interiorul unui bloc de tip checked. In ¸ eroarea de dep˘¸ire este ignorat˘.

Dac˘ literalul specificat nu a a a poate fi reprezentat ˆ tipul precizat. Dac˘ ˆ urma operatiilor. Literalii a s care se pot folosi sunt true ¸i false. apare eroare de compilare.2. atunci el a este f˘cut 0. ın Tipul decimal Este un tip de date reprezentat pe 128 de biti. f˘r˘ conversii explicite. cifre-zecimale exponentoptional sufix-de-tip-realoptional . gˆndit a fi folosit ˆ calcule ¸ a ın financiare sau care necesit˘ precizie mai mare. d. infinit sau NaN.2. a ın ¸ un num˘r este prea mic pentru a putea fi reprezentat ca decimal. sufix-de-tip-real este F. ˆ ıntr–o manier˘ clar˘ ¸i sigur˘ din punct de vedere al a as a . aa Literalii de acest tip se exprim˘ folosind ca sufix-de-tip-real caracterele m a sau M. iar dac˘ este prea mare. d sau D specific˘ double. semn este + sau -. a a a apare o eroare la compilare. s 2. cu 28 de cifre semnificative. D. Din cauza aceasta. Diferenta principal˘ a a a ¸ ¸ a fat˘ de tipurile ˆ virgul˘ mobil˘ este c˘ are o precizie mai mare.0 × 10−28 ¸i 7. Acest tip ın s nu poate reprezenta zero cu semn. Dac˘ valoarea specificat˘ nu poate fi reprezentat˘ prin tipul decimal. dar un ¸a ın a a a domeniu de reprezentare mai mic. Poate reprezenta valori aflate a ˆ intervalul 1. Nu exist˘ conversii standard ˆ s a ıntre bool ¸i nici un alt tip.2. unde exponent:: e semnoptional cifre-zecimale E semnoptional cifre-zecimale.9 × 1028 . rezult˘ o exceptie. nu se fac conversii implicite ˆ ıntre nici un tip ˆ virgul˘ mobil˘ ¸i decimal ¸i nu este posibil˘ ın a a s s a mixarea variabilelor de acest tip ˆ ıntr-o expresie. Sufixul f sau F specific˘ tip float. cifre-zecimale exponentoptional sufix-de-tip-realoptional cifre-zecimale exponent sufix-de-tip-realoptional cifre-zecimale sufix-de-tip-real.3 Tipul enumerare Tipul enumerare este un tip valoare. Dac˘ nici un sufix de tip a real nu este specificat. Tipul bool Este folosit pentru reprezentarea valorilor de adev˘r true ¸i false. f. TIPURI DE DATE 29 Literalii care specific˘ un num˘r reprezentat ˆ virgul˘ mobil˘ au forma: a a ın a a literal–real:: cifre-zecimale . construit pentru a permite declararea constantelor ˆ ınrudite. atunci literalul dat este de tip double.

Solid) { //cod desenare linie continua } else if (lineStyle == LineStyle. STRING-URI tipului.Dotted) { //cod desenare linie punctata } else if (lineStyle == LineStyle. TABLOURI. DotDash } public void DrawLine(int x1. TIPURI PREDEFINITE. Un exemplu este: using System.DotDash) { //cod desenare segment linie-punct } else { throw new ArgumentException(‘‘Invalid line style’’). LineStyle lineStyle) { if (lineStyle == LineStyle. } } } class Test { public static void Main() { Draw draw = new Draw(). int y2. public class Draw { public enum LineStyle { Solid Dotted.30 CURS 2. int x2. . int y1.

Enum. 9 Engl: underlying type . 0. 10. 10. large } Specificarea este folosit˘ atunci cˆnd dimensiunea ˆ memorie este impora a ın tant˘. Orice a s enum este derivat automat din System. metodele mo¸tenite de la tipurile p˘rinte sunt s a utilizabile de c˘tre orice variabil˘ de tip enum. s Enumer˘rile nu pot fi declarate abstracte ¸i nu pot fi derivate. se sugereaz˘ folosirea conventiei s a a ¸ Pascal atˆt pentru numele tipului cˆt ¸i pentru numele valorilor continute.LineStyle)100). pentru a se cunoa¸te cˆt spatiu de memorie trebuie s˘ fie alocat unei variabile de s a ¸ a acest tip. 10. Ca ¸i mod de scriere a enumer˘rilor. Draw. exceptˆnd tipul char) se face prin enuntarea tipului a ¸ dup˘ numele enumer˘rii: a a enum MyEnum : byte { small.2. deoarece valorile care se pot specifica pentru un enum nu sunt limitate la valorile declarate ˆ enum.DrawLine(0. (Draw.Solid).LineStyle. sau cˆnd se dore¸te crearea unui tip de indicator (un tip flag) al c˘rui a a s a num˘r de st˘ri difer˘ de num˘rul de biti alocati tipului int (modelare de a a a a ¸ ¸ flag-uri): enum ActionAttributes : ulong { Read = 1. a a a ¸ ˆ cazul de fat˘.ValueType). care este la rˆndul lui derivat a din System. Dac˘ nu se specific˘ nici un tip de reprezentare (ca mai sus). Ca atare. la apelul de metod˘ se arunc˘ o exceptie (exceptiile vor fi In ¸a a a ¸ ¸ tratate pe larg ˆ ıntr-un curs viitor). Write = 2.2. Delete = 4. } } 31 Al doilea apel este legal. TIPURI DE DATE draw.DrawLine(0. 10. atunci a a se presupune implicit tipul int. a a Fiecare tip enumerare care este folosit are un tip de reprezentare9 . astfel. programatorul ın trebuie s˘ fac˘ valid˘ri suplimentare pentru a determina consistenta valorilor. Specificarea unui tip de reprezentare (care poate fi orice tip integral. Query = 8. a a s ¸ precum ¸i evitarea folosirii prefixelor sau sufixelor pentru acestea. draw. 0.

failed = 1. ¸i In s fiecare variabl˘ care urmeaz˘ are valoarea mai mare cu o unitate decˆt precea a a denta. c = a + b } Urm˘toarele observatii se impun relativ la lucrul cu tipul enumerare: a ¸ 1. valoarea primului membru al unei structuri este 0. TIPURI PREDEFINITE. ˆ mod implicit.Read|ActionAttributes.. b = 2. . acesta va lua valoarea a a membrului precedent + 1 (cu exceptia primului membru – vezi mai ¸ sus) . dac˘ pentru un membru nu este dat˘ o valoare.. TABLOURI.Write | ActionAttributes. STRING-URI Sync = 16 //etc } . La dorint˘. valorile specificate ca initializatori trebuie s˘ fie reprezentabile prin ¸ a tipul de reprezentare a enumer˘rii.. mai multi membri pot avea aceea¸i valoare (manevr˘ dictat˘ de seman¸ s a a tica tipului construit): enum ExamState { passed = 10.32 CURS 2. rejected = failed } 3.Query. ActionAttributes aa=ActionAttributes. altfel apare o eroare la compilare: a enum Out : byte { A = -1 }//eroare semnalata la compilare 2.. valoarea fiec˘rei variabile poate fi specificat˘ explicit: ¸a a a enum Values { a = 1.

2.2. TIPURI DE DATE 4. nu se permit referinte circulare: ¸ enum CircularEnum { A = B, B }//A depinde explicit de B, B depinde implicit de A //eroare semnalata la compilare

33

5. este recomandat ca orice tip enum s˘ contin˘ un membru cu valoarea a ¸ a 0, pentru c˘ ˆ anumite contexte valoarea implicit˘ pentru o variabil˘ a ın a a enum este 0, ceea ce poate duce la inconsistente ¸i bug-uri greu de ¸ s depanat enum Months { InvalidMonth,//are valoarea implicita 0, fiind primul element January, February, //etc } Tipurile enumerare pot fi convertite c˘tre tipul lor de baz˘ ¸i ˆ a a s ınapoi, folosind o conversie explicit˘ (cast): a enum Values { a = 1, b = 5, c= 3 } class Test { public static void Main() { Values v = (Values)3; int ival = (int)v; } } Valoarea 0 poate fi convertit˘ c˘tre un enum f˘r˘ cast: a a aa

34

CURS 2. TIPURI PREDEFINITE, TABLOURI, STRING-URI ... MyEnum me; ... if (me == 0) { //cod }

Urm˘torul cod arat˘ cˆteva din artificiile care pot fi aplicate tipului a a a enumerare: obtinerea tipului unui element de tip enumerare precum ¸i a ¸ s tipului clasei de baz˘, a tipului de reprezentare, a valorilor continute (ca a ¸ nume simbolice ¸i ca valori), conversie de la un string la un tip enumers are pe baza numelui, etc. Exemplul este preluat din <FrameworkSDK> \Samples\Technologies\ValueAndEnumTypes. using System; namespace DemoEnum { class DemoEnum { enum Color { Red = 111, Green = 222, Blue = 333 } private static void DemoEnums() { Console.WriteLine("\n\nDemo start: Demo of enumerated types."); Color c = Color.Red; // What type is this enum & what is it derived from Console.WriteLine(" The " + c.GetType() + " type is derived from " + c.GetType().BaseType); // What is the underlying type used for the Enum’s value Console.WriteLine(" Underlying type: " + Enum.GetUnderlyingType( typeof(Color))); // Display the set of legal enum values

2.2. TIPURI DE DATE

35

Color[] o = (Color[]) Enum.GetValues(c.GetType()); Console.WriteLine("\n Number of valid enum values: " + o.Length); for (int x = 0; x < o.Length; x++) { Color cc = ((Color)(o[x])); Console.WriteLine(" {0}: Name={1,7}\t\tNumber={2}", x, cc.ToString("G"), cc.ToString("D")); } // Check if a value is legal for this enum Console.WriteLine("\n 111 is a valid enum value: " + Enum.IsDefined( c.GetType(), 111)); // True Console.WriteLine(" 112 is a valid enum value: " + Enum.IsDefined( c.GetType(), 112)); // False // Check if two enums are equal Console.WriteLine("\n Is c equal to Red: " + (Color.Red == c));//True Console.WriteLine(" Is c equal to Blue: " + (Color.Blue == c));//False // Display the enum’s value as a string using different format specifiers Console.WriteLine("\n c’s value as a string: " + c.ToString("G"));//Red Console.WriteLine(" c’s value as a number: " + c.ToString("D"));//111 // Convert a string to an enum’s value c = (Color) (Enum.Parse(typeof(Color), "Blue")); try { c = (Color) (Enum.Parse(typeof(Color), "NotAColor"));//Not valid, //raises exception } catch (ArgumentException) { Console.WriteLine(" ’NotAColor’ is not a valid value for this enum."); } // Display the enum’s value as a string Console.WriteLine("\n c’s value as a string: " + c.ToString("G"));//Blue Console.WriteLine(" c’s value as a number: " + c.ToString("D"));//333 Console.WriteLine("Demo stop: Demo of enumerated types."); }

36

CURS 2. TIPURI PREDEFINITE, TABLOURI, STRING-URI

static void Main() { DemoEnums(); } } }

2.3

Tablouri

ˆ cele mai multe cazuri nu se cunoa¸te aprioric num˘rul de obiecte care In s a se vor folosi la momentul rul˘rii. O solutie pentru stocarea elementelor avˆnd a ¸ a acela¸i tip o reprezint˘ tablourile. Sintaxa de declarare este asem˘n˘toare s a a a cu cea din Java sau C++, dar fiecare tablou este un obiect, derivat din clasa abstract˘ System.Array. Accesul la elemente se face prin intermediul indicilor a care ˆ ıncep de la 0 ¸i se termin˘ la num˘rul de elemente-1; orice dep˘¸ire a s a a as indicilor duce la aparitia unei exceptii: System.IndexOutOfRangeException. ¸ ¸ O variabil˘ de tip tablou poate avea valoare de null sau poate s˘ indice c˘tre a a a o instant˘ valid˘. ¸a a

2.3.1

Tablouri unidimensionale

Declararea unui tablou unidimensional se face prin plasarea de paranteze drepte ˆ ıntre numele tipului tabloului ¸i numele s˘u, ca mai jos10 : s a int[] sir; Declararea de mai sus nu duce la alocare de spatiu pentru memorarea ¸irului; ¸ s instatierea se poate face ca mai jos: ¸ sir = new int[10]; Exemplu: using System; class Unidimensional { public static int Main() { int[] sir; int n;
Spre deosebire de Java, nu se poate modifica locul parantezelor, adic˘ nu se poate a scrie: int sir[].
10

2.3. TABLOURI Console.Write(‘‘Dimensiunea vectorului: ’’); n = Int32.Parse( Console.ReadLine() ); sir = new int[n]; for( int i=0; i<sir.Length; i++) { sir[i] = i * i; } for( int i=0; i<sir.Length; i++) { Console.WriteLine(‘‘sir[{0}]={1}’’, i, sir[i]); } return 0; } }

37

ˆ acest exemplu se folose¸te proprietatea11 Length, care returneaz˘ num˘rul In s a a tuturor elementelor vectorului (lucru vizibil la tablourile multidimensionale rectangulare). De mentionat c˘ ˆ acest context n ¸i sir nu se pot declara ¸ a ın s la un loc, adic˘ declaratii de genul int[] sir, n; sau int n, []sir; sunt a ¸ incorecte (prima este corect˘ din punct de vedere sintactic, dar ar rezulta c˘ a a n este ¸i el un tablou; ˆ al doilea caz, declaratia nu este corect˘ sintactic). s ın ¸ a Se pot face initializ˘ri ale valorilor continute ˆ ¸ a ¸ ıntr–un tablou: int[] a = new int[] {1,2,3}; sau ˆ forma mai scurt˘: ın a int[] a = {1,2,3};

2.3.2

Tablouri multidimensionale

C# cunoa¸te dou˘ tipuri de tablouri multidimensionale: rectangulare ¸i s a s 12 neregulate . Numele lor vine de la forma pe care o pot avea. Tablouri rectangulare Tablourile rectangulare au proprietatea c˘ pe fiecare dimensiune se afl˘ a a acela¸i num˘r de elemente. Se declar˘ ca ˆ exemplul de mai jos: s a a ın int[,] tab;
11 12

Pentru notiunea de proprietate, vezi la partea despre clase. ¸ Engl: jagged arrays.

j<tabInm. i<tabInm. s La declararea tabloului se poate face ¸i initializare: s ¸ int[. i++ ) { for( int j=0.Length=100.Length={0}’’.2}. mai pe scurt: int[. rezultˆnd un tablou cu 2 linii ¸i 3 coloane. TIPURI PREDEFINITE. } } Console.4}}. se va afi¸a: tabInm. STRING-URI unde tab este un tablou rectangular bidimensional.WriteLine(‘‘{0}*{1}={2}’’.3]. class Test { public static void Main() { int[. } } for( int i=0.WriteLine(‘‘tabInm.GetLength(1).] tab = new int[. i<tabInm.] tabInm = new int[10. tabInm.j] = i * j.GetLength(0). Exemplu: using System. TABLOURI.{3. Referirea la elementul aflat pe a s linia i ¸i coloana j se face cu tab[i.] {{1.] tab = {{1.GetLength(0). sau. tabInm[i. j++) { Console. Instantierea se face: ¸ tab = new int[2. i. {3. j<tabInm. j. 4}}.j]).GetLength(1).38 CURS 2. j++) { tabInm[i. Am folosit ˆ a metoda GetLength(d) care returneaz˘ ıns˘ a . 2}.Length). i++) { for( int j=0.10]. for( int i=0. j]. } } Dup˘ ce se afi¸eaz˘ tabla ˆ a s a ınmultirii pˆn˘ la 10. ¸ a a s deoarece proprietatea Length d˘ num˘rul total de elemente aflat ˆ tablou (pe a a ın toate dimensiunile).

7]. s Exemplu: using System.4]. t3. Declararea unui a tablou neregulat cu dou˘ dimensiuni se face ca mai jos: a int[][] tab. int[.WriteLine(‘‘t1. int[.Rank=3 Tablouri neregulate Un tablou neregulat13 reprezint˘ un tablou de tabouri.Rank={1}\nt3. 13 Engl: jagged array . Referirea la elementul de indici i ¸i j se face prin tab[i][j]. Console. } } Pe ecran va ap˘rea: a t1.Rank={2}’’.Rank.2.. Determinarea num˘rului de dimensiuni pentru un tablou rectangular la a run–time se face folosind proprietatea Rank a clasei de baz˘ System.] t2 = new int[3. TABLOURI 39 num˘rul de elemente aflate pe dimensiunea num˘rul d (num˘rarea dimensia a a unilor ˆ ıncepe cu 0). t1.Rank. class Dimensiuni { public static void Main() { int[] t1 = new int[2].Rank).Array. a[0] = new int[2].Rank={0}\nt2.Rank=2 t3. a Exemplu: using System. t2.] t3 = new int[5.3. class JaggedArray { public static void Main() { int[][] a = new int[2][].6.Rank=1 t2.

new int[] {0.Length.4.7. . i++) { a[0][i] = i. new int[] {11.3. new int[] {0.4. STRING-URI a[1] = new int[3].Length.7. deci este unidimensional.40 CURS 2. i<a[1].2.Length.Length.9}.9}. } for(int i=0. ¸ ¸ Initializarea valorilor unui tablou neregulat se poate face la declarare: ¸ int[][] myJaggedArray = new int [][] { new int[] {1. new int[] {11. TABLOURI.5.6}. } Console. i++) { for( int j=0. } } va scrie pe ecran: 0 1 0 1 4 a.6}.Rank=1 Ultima linie afi¸at˘ se explic˘ prin faptul c˘ un tablou neregulat este un s a a a vector care contine referinte. } for( int i=0.22} }.Rank={0}’’. a. j<a[i].WriteLine(). TIPURI PREDEFINITE. } Console. a[i][j]). i<a. for( int i=0.WriteLine(‘‘a.5.2. i<a[0].22} }. j++ ) { Console.Write(‘‘{0} ’’.3.Rank). i++) { a[1][i] = i * i. Forma de mai sus se poate prescurta la: int[][] myJaggedArray = { new int[] {1.

Un literal de acest tip are simbolul ”@” ˆ s ınaintea ghilimelelor de ˆ ınceput. Operatorii ”==” ¸i ”!=” pentru dou˘ ¸iruri de caractere se comport˘ s a s a ˆ felul urm˘tor: dou˘ ¸iruri de caractere se consider˘ egale dac˘ sunt fie ın a a s a a amˆndou˘ null.4.". //ghilimelele se dubleaza intr-un verbatim string String s=@"notiunea ""aleator"" se refera. Obiectele de acest tip sunt imutabile (caracterele continute nu se pot schimba.". Pentru a se compara dou˘ a ¸ a ¸iruri din punct de vedere al referintelor.. SIRURI DE CARACTERE ¸ 41 2. trebuie ca m˘car unul dintre obiecte s ¸ a s˘ fie convertit la object: a class Test { public static void Main() { 14 Engl: verbatim literals .4 Siruri de caractere ¸ Tipul de date folosit pentru reprezentarea ¸irurilor de caractere este clasa s System. fie au aceea¸i lungime ¸i caracterele de pe acelea¸i pozitii a a s s s ¸ coincid.2. ”!=” d˘ negarea relatiei de egalitate. s ın s s Exemple: String caleCompleta=@"\\minimax\protect\csharp". ¸ s ¸ s Sirurile pot contine secvente escape ¸i pot fi de dou˘ tipuri: regulate ¸i de ¸ ¸ ¸ s a s tip ”verbatim”14 . //string multilinie reprezentat ca verbatim String dialog=@"-Alo? Cu ce va ajutam? -As avea nevoie de o informatie. ¸ Exemplu: String a = "string literal". dar pe baza unui ¸ir se poate obtine un alt ¸ir). Sirurile verbatim sunt folosite pentru a face referiri aa ¸ la fi¸iere sau chei ˆ regi¸tri. ın ıntˆ ın s ele se vor dubla.. Pentru situatia ˆ care se utilizeaz˘ masiv secvente escape. sau pentru prelucrarea fi¸ierelor.String (pentru care se poate folosi aliasul ”string”. Sirurile regulate sunt demarcate prin ghilimele ¸i necesit˘ ¸ s a secvente escape pentru reprezentarea caracterelor escape. String versuri = "vers1\nvers2". se pot folosi ¸ ın a ¸ ¸irurile verbatim. reamintim c˘ a este un tip predefinit). Un ¸ir de caractere poate fi reprezentat pe mai multe rˆnduri s a f˘r˘ a folosi caracterul \n. String caleCompleta = "\\\\minimax\\protect\\csharp". Pentru cazul ˆ care ghilimelele sunt ˆ alnite ˆ interiorul ¸irului.

modificare (a se ˆ ¸elege obtinerea altor obiecte pe baza celui curent ınt ¸ . Remove. Join. STRING-URI string a = "Salut". c˘utare (EndsWith. i++) { Console. TABLOURI. System. Insert. . (object)a==b).WriteLine("a==b: {0}". StartsWith. String[] tokens = s. b = a. s ¸ s ˆ clasa object se afl˘ metoda ToString() care este suprascris˘ ˆ fiecare In a a ın clas˘ ale c˘rei instante pot fi tip˘rite. s += "!!!!". s Un exemplu de folosire a functiei Split() pentru desp˘rtirea unui ¸ir ˆ ¸ a¸ s ın functie de separatori este: ¸ using System. for(int i=0.Length. CopyTo. Com¸ pareOrdinal. char[] x = {’ ’. reprezentˆnd concatenarea: a String s = "Salut" + " " + "lume".Format(). IndexOf.WriteLine("Token: {0}". Pentru obtinerea unei reprezent˘ri a a ¸ a ¸ a diferite se folose¸te metoda String.WriteLine("(object)a==b: {0}". PadRight. i<tokens. PadLeft. } } La dispozitivul standard de ie¸ire se va afi¸a: s s a==b: true (object)a==b: false Alt operator care se poate utiliza este ”+”. Trim. Split. 15 A se vedea exemplele din MSDN. a==b). ToLower.’ }. Accesarea unui caracter aflat pe o pozitie i a unui ¸ir s se face prin folosirea parantezelor ¸ s drepte. class Class1 { static void Main(string[] args) { String s = "Oh. TrimEnd. LastIna dexOf). TIPURI PREDEFINITE.Console. System. I hadn’t thought of that!".Split( x ). TrimStart)15 . Substring. ToUpper.Concat. cu acelea¸i restrictii asupra indicelui ca ¸i pentru tablouri: s[i].Clone().Console. Replace. tokens[i]). Clasa String pune la dispozitie metode pentru: comparare (Compare. ’. CompareTo).42 CURS 2.

Pentru aceasta ın ¸ a ¸ se folosesc expresii regulate. Pentru a lucra cu ¸iruri de caractere care permit modificarea lor se folose¸te s s clasa StringBuilder. a Exemplul anterior poate fi rescris corect din puct de vedere al functionalit˘¸ii ¸ at prin folosirea unei expresii regulate. In ın ¸ namespace–ul System.Text. s ¸ lucru care ar fi de dorit ˆ prezenta a doi separatori al˘turati. Al doilea lucru care trebuie explicat este c˘ al ın s a doilea token este cuvˆntul vid.Text. se scrie o secvent˘ ”din mers” pentru a t a ¸a implementa potrivirea expresiei regulate.4.4.1 Expresii regulate ˆ cazul ˆ care functiile din clasa String nu sunt suficient de puternice. Forma expresiilor regulate este cea din limbajul Perl. Expresiile regulate reprezint˘ o a a metod˘ extrem de facil˘ de a opera c˘ut˘ri/ˆ a a a a ınlocuiri pe text. dup˘ care codul este rulat16 .RegularExpresions pune la dispozitie o clas˘ de ¸ a lucru cu expresii regulate numit˘ Regex. SIRURI DE CARACTERE ¸ } } } va afi¸a pe ecran: s Token: Token: Token: Token: Token: Token: Token: Oh I hadn’t thought of that! 43 De remarcat c˘ pentru caracterul apostrof nu este obligatorie secventa escape a ¸ ˆ cazul ¸irurilor de caractere. ın . care apare ˆ a ıntre cei doi separatori al˘turati: a ¸ virgula ¸i spatiul. pentru a prinde ¸i cazul separatorilor s multipli adiacenti: ¸ class ExpresieRegulata { static void Main(string[] args) { 16 Codul este scris direct ˆ IL. 2. din namespace–ul System. Metoda Split() nu face gruparea mai multor separatori.2. Aceast˘ clas˘ folose¸te o tehnic˘ interesant˘ pentru m˘rirea performana a s a a a ¸elor: dac˘ programatorul vrea.

WriteLine("Word: {0}". i<strs. strs[i]).Split(s). . //separator: virgula. TABLOURI. TIPURI PREDEFINITE. orice combinatie Regex regex = new Regex("[.Length. I hadn’t thought of that!". for( int i=0. String[] strs = regex. STRING-URI String s = "Oh. spatiu sau punct si virgula //unul sau mai multe. } } care va produce: Word: Word: Word: Word: Word: Word: Oh I hadn’t thought of that! .]+").44 CURS 2. i++) { Console.

tipuri imbricate. O descriere este dat˘ ˆ tabelul 3. operatori. 45 .1 Clase – vedere general˘ a Clasele reprezint˘ tipuri referint˘ definite de utilizator. at Instructiuni. ¸ a at indexatori. Spatii de nume ¸ ¸ 3. destructori. a ¸ care controleaz˘ gradul de acces la el. constructori de ¸a clas˘. metode. evenimente. constructori de instant˘. cˆmpuri. propriet˘¸i.1: a a ın Tabelul 3. s a a as ¸ Clasele pot contine constante.Curs 3 Clase – generalit˘¸i. O clas˘ poate s˘ a ¸a a a mo¸teneasc˘ o singur˘ clas˘ ¸i poate implementa mai multe interfete.1: Modificatori de acces ai membrilor unei clase Accesor public protected Semnificatie ¸ Acces nelimitat Acces limitat la clasa contin˘toare ¸ a sau la tipuri derivate din ea internal Acces limitat la acest assembly protected internal Acces limitat la acest assembly sau la tipuri derivate din clas˘ a private Acces limitat la clas˘. a modificatorul implicit de acces using System. Fiecare membru poate contine un nivel de accesare.

public void MyMethod() { Console. } set { MyField = value. public int MyField = 34. } } public event EventHandler MyEvent.MyMethod"). public static MyClass operator+(MyClass a.WriteLine("this[{0}]={1}". } public const int MyConst = 12. } set { Console. SPATII DE NUME ¸ ¸ class MyClass { public MyClass() { Console. value).WriteLine("MyClass. } public int MyProperty { get { return MyField. MyClass b) . CLASE. Console. } } public int this[int index] { get { return 0.46 CURS 3.WriteLine("Constructor instanta"). index.WriteLine("Constructor instanta"). } public MyClass( int value ) { MyField = value. INSTRUCTIUNI.

MyConst). a. a. a.MyConst). a[3]). Console. a a a a .MyEvent += new EventHandler(MyHandler).MyField). } } class Test { static void Main() { MyClass a = new MyClass(). ¸i nu prin intermediul a s vreunei instante (a.1.MyField={0}". } static void MyHandler(object Sender. CLASE – VEDERE GENERALA { return new MyClass(a.WriteLine("MyConst={0}". MyClass c = a + b.MyField).MyMethod(). a a care poate fi evaluat˘ la compilare. a.MyProperty++.MyHandler").WriteLine("a.WriteLine("a[3]={0}". } internal class MyNestedType {} } 47 Constanta este un membru al unei clase care reprezint˘ o valoare constant˘. a. MyClass b = new MyClass(1).MyProperty={0}". Constantele pot depinde de alte a constante. a[3] = a[1] = a[2]. ¸ Cˆmpul este un membru reprezentˆnd o variabil˘ asociat˘ unui obiect.WriteLine("a. MyClass. Console. Ele pot fi accesate exclusiv prin inın ¸ termediul numelui de clas˘ (MyClass. Console.MyProperty).MyField++. a. Console. EventArgs e) { Console.MyField + b.˘ 3.WriteLine("Test.MyConst). atˆta timp cˆt nu se creeaz˘ dependente circulare. Ele sunt a a a ¸ considerate automat membri statici (dar este interzis s˘ se foloseasc˘ a a specificatorul static ˆ fata lor).

CLASE. Proprietatea este un membru care d˘ acces la o caracteristic˘ a unui obiect a a sau unei clase. System. Exemplu: a at public delegate void EventHandler(object sender. Reprezint˘ a s at s a o alt˘ modalitate de implementare a accesorilor pentru obiecte. Metodele a statice (care au ˆ antet cuvˆntul cheie static) sunt accesate prin interın a mediul numelui de clas˘. public Form1() { Button1. . pe cˆnd cele nestatice (metode instant˘) sunt a a ¸a apelate prin intermediul unui obiect. Tipul acestei a ¸ a declaratii trebuie s˘ fie un tip delegat. public class Form1 { Button Button1 = new Button1().EventArgs e).48 CURS 3. } } using System. EventArgs e ) { Console.Click += new EventHandler(Button1_Click). Exemplele folosite pˆn˘ acum includeau lungimea unui a a vector. O instant˘ a unui tip delegat ¸ a ¸a ˆ ıncapsuleaz˘ una sau mai multe entit˘¸i apelabile.WriteLine("Button1 was clicked!"). public class Button { public event EventHandler Click. } void Button1_Click(object sender. num˘rul de caractere ale unui ¸ir de caractere. SPATII DE NUME ¸ ¸ Metoda este un membru care implementeaz˘ un calcul sau o actiune care a ¸ poate fi efectuat˘ asupra unui obiect sau asupra unei clase. etc. public void Reset() { Click = null. a Evenimentul este un membru care permite unei clase sau unui obiect s˘ a pun˘ la dispozitia altora notific˘ri asupra evenimentelor. Sintaxa a s pentru accesara cˆmpurilor ¸i a propriet˘¸ilor este aceea¸i. INSTRUCTIUNI.

2 Transmiterea de parametri ˆ general. ¸a nu poate avea modificatori de acces. s Indexatorul este un membru care permite unui obiect s˘ fie indexat ˆ a ın acela¸i mod ca un tablou (pentru programatorii C++: supraˆ arcarea s ınc˘ operatorului []). TRANSMITEREA DE PARAMETRI } public void Disconnect() { Button1. nu pot avea modificatori de acces. Nu ¸ a pot avea parametri. mai exact membrii statici ai clasei. Acest lucru In ˆ ınseamn˘ c˘ la apelul unei metode ˆ stiva gestionat˘ de compilator se copiaz˘ a a ın a a 1 Engl: event handler .Click -= new EventHandler(Button1_Click). iar r˘d˘cina ierarhiei este clasa object (alias s a a System. 3. ¸ a Destructorul este un membru special care implementeaz˘ actiunile cerute a ¸ pentru a distruge o instant˘ a unei clase. Constructorii instant˘ sunt membri care implementeaz˘ actiuni cerute ¸a a ¸ pentru initializarea fiec˘rui obiect.3.2. nu poate fi apelati explicit ¸i poate ¸ s fi apelat automat de c˘tre garbage collector. a Mo¸tenirea este de tip simplu. unari ¸i de conversie. } } 49 Mai sus clasa Form1 adaug˘ Button1 Click ca tratare de eveniment1 a pentru evenimentul Click al lui Button1. a Constructorul static este un membru care implementeaz˘ actiuni necea ¸ sare pentru a initializa o clas˘. Destructorul nu are parametri. nu sunt apelati ¸ explicit. acest In event handler este ˆ aturat. transmiterea parametrilor se face prin valoare. ci automat de c˘tre sistem.Object). ˆ metoda Disconnect(). ınl˘ Operatorul este un membru care define¸te semnificatia (supraˆ arcarea) s ¸ ınc˘ unui operator care se aplic˘ instantelor unei clase. Se pot supraˆ arca a ¸ ınc˘ operatorii binari.

x ). ++x. f( a ). } } Executarea acestui program va avea ca rezultat: inainte de intrare in f: 100 la intrare in f: 100 la iesire din f: 101 dupa executarea lui f: 100 Pentru variable de tip referint˘.50 CURS 3. SPATII DE NUME ¸ ¸ valoarea parametrului actual transmis. } class Test .WriteLine("la iesire din f: {0}". Console. public decimal salary.WriteLine("la intrare in f: {0}". class DemoTipValoare { static void f(int x) { Console. iar la revenire din metod˘ aceast˘ a a valoare va fi ¸tears˘. INSTRUCTIUNI. Exemplific˘m mai jos acest lucru pentru tipurile valoare s a a ¸i referint˘.WriteLine("dupa executarea lui f: {0}". a). } static void Main() { int a = 100. Ca atare. Console. s ¸a using System. pe stiv˘ se depune tot o copie a valorii ¸a a ˆ a pentru un asemenea tip de variabil˘ acest lucru ˆ obiectului. Console. metoda apelat˘ poate s˘ modifice starea obiectului care a a se transmite: class Employee { public String name. x ). a).WriteLine("inainte de intrare in f: {0}". Ins˘ a ınseamn˘ c˘ a a pe stiv˘ se va depune ca valoare adresa de memorie la care eset stocat obiectul a respectiv. CLASE.

e.Console. Console. TRANSMITEREA DE PARAMETRI { static void Main() { Employee e = new Employee(). System. salary={1}". myClass. myClass. } static void Method( Employee e ) { e. salary=300 post: name=Ionescu.x).WriteLine("intrare in f: {0}". salary=400 51 Totu¸i.WriteLine("post: name={0}.x = -100.WriteLine("iesire din f: {0}". e.salary ). } .salary = 300M.salary += 100.3. System. } } va avea ca rezultat: pre: name=Ionescu. myClass. chiar ¸i ˆ cazul tipului referint˘ ˆ s s ın ¸a ıncercarea de a re–crea ˆ interiın orul unei metode un obiect transmis ca parametru nu are nici un efect dup˘ a terminarea ei: class MyClass { public int x. e. e.x). e. e.Console. } class Test { static void f(MyClass myClass) { Console.salary ). Method( e ).2. myClass = new MyClass().name.WriteLine("pre: name={0}.name = "Ionescu".name. salary={1}".

myClass. y). } } . y={1}". Swap( ref a. y=2. myClass. Console. y={1}". x. INSTRUCTIUNI. SPATII DE NUME ¸ ¸ static void Main() { MyClass myClass = new MyClass(). a = b. ref int b) { int t = a. f( myClass ). y). Pentru a transmite un parametru prin referint˘. b = t.WriteLine("inainte de apel: x={0}. a a ¸a se prefixeaz˘ cu cuvˆntul cheie ref la apel sau la declarare de metod˘: a a a using System. class Test { static void Swap( ref int a.x = 100.x).WriteLine("inainte de apel: {0}". Console.WriteLine("dupa apel: x={0}.WriteLine("dupa apel: {0}". folosind referint˘ (un alias) pentru entitatea dat˘ ¸a a de c˘tre metoda apelant˘. Un parametru referint˘ este folosit tocmai pentru a rezolva problema ¸a transmiterii prin valoare. } static void Main() { int x=1. myClass. ref b ) Console. } } Ie¸irea acestui program va fi: s inainte de intrare in iesire din dupa apel: apel: 100 f: 100 f: -100 100 Exist˘ situatii ˆ care acest comportament nu este cel dorit: am vrea ca a ¸ ın efectul asupra unui parametru s˘ se mentin˘ ¸i dup˘ ce metoda apelat˘ s–a a ¸ as a a terminat.52 CURS 3. Console. CLASE.x). x.

WriteLine("Area is: {0}". mesajul fiind: ”Use of unassigned local variable ’x’”. Neasignarea de valori pentru x a ¸ ¸i y ˆ exemplul de mai sus duce o eroare de compilare. s Una din tr˘s˘turile specifice parametrilor referint˘ este c˘ valorile pentru aa ¸a a care se face apelul trebuie s˘ fie initializate. TRANSMITEREA DE PARAMETRI 53 va realiza interschimbarea valorilor a ¸i b. class TestRef { static void f(ref int x) { x = 100. Pentru aceasta exist˘ parametrii de ie¸ire2 . cu deosebirea c˘ nu trebuie asignat˘ o valoare ¸a a a parametrului de apel: using System. out double area ) { 2 Engl: output parameters . class Test { static void Main() { int l = 10. dar f˘r˘ a trebui s˘ initializ˘m argumentele date de c˘tre metoda ¸a aa a ¸ a a apelant˘ (de exemplu cˆnd valoarea acestui parametru se calculeaz˘ ˆ ina a a ın teriorul metodei apelate). exemplul s ın de mai jos genereaza eroare la compilare.3. Console. out area). simia s lar cu parametrii referint˘. Mai clar. ComputeSquareArea( l. } } Exist˘ cazuri ˆ care dorim s˘ obtinem acela¸i efect ca la parametrii a ın a ¸ s referint˘. area).2. double area. } static void ComputeSquareArea( double l. f(ref x). } static void Main() { int x.

e. F(1). F(1. class Test { static void F(params int[] args) { Console. F(new int[] {1. args. Un astfel de parametru se declar˘ a folosind modificatorul params. SPATII DE NUME ¸ ¸ area = l * l.54 CURS 3.3}). Acest parametru formal este tratat ca un tablou unidimensional: using System. i.WriteLine("args[{0}]={1}".Length). for( int i=0.2.2). i. params object[] args){. CLASE. i<args.} 3 Engl: parameter array . } } static void Main() { F(). INSTRUCTIUNI. exist˘ ˆ aceast˘ clas˘ o metod˘ de tipul: a ın a a a public static void WriteLine(string format. } } Pentru toate tipurile de parametri de mai sus exist˘ o mapare 1 la 1 ˆ a ıntre 3 parametrii actuali ¸i cei formali. i++) { Console..WriteLine("# of parameters: {0}". putem a avea cel mult un parametru de tip vector ¸i acesta trebuie s˘ fie ultimul ˆ s a ın lista de parametri. } } Acest tip de transmitere se folose¸te ¸i de c˘tre metoda WriteLine (sau Write) s s a a clasei Console.. args[i]). Un parametru vector permite o relatie s ¸ de tipul unul-la-multi: mai multi parametri actuali pot fi referite prin in¸ ¸ termediul unui singur parametru formal. Pentru o implementare de metod˘.Length.

3. float. CONVERSII 55 3.3. double. decimal. long. decimal. int. de exemplu ¸ apeluri de functii sau atribuiri.3 Conversii O conversie permite ca o expresie de un anumit tip s˘ fie tratat˘ ca fiind a a de alt tip. . long. ushort. • de la short la int.3. • de la ushort la int. long. Conversiile implicite predefinite nu determin˘ ¸ a niciodat˘ aparitia de exceptii. float. int. a ¸ ¸ Conversiile indentitate O conversie identitate converte¸te de la un tip oarecare c˘tre acela¸i tip. decimal. • de la byte la short. double. float.1 Conversii implicite Sunt clasificate ca ¸i conversii implicite urm˘toarele: s a • conversiile identitate • conversiile numerice implicite • conversiile implicite de tip enumerare • conversiile implicite de referinte ¸ • boxing • conversiile implicite ale expresiilor constante • conversii implicite definite de utilizator Conversiile implicite pot ap˘rea ˆ a ıntr–o varietate de situatii. float. s a s Conversiile numerice implicite Conversiile numerice implicite sunt: • de la sbyte la short. uint. aceasta specificˆnd de a fapt dac˘ un operator de cast (conversie) este sau nu necesar. decimal. decimal. double. Conversiile pot fi implicite sau explicite. double. long. a 3. ulong. double. ulong. uint. • de la int la long.

decimal. float.56 CURS 3. • de la long la float.Array. dac˘ A este derivat˘ din B. double. long. decimal. • de la char la ushort. double. a ¸a a a • de al orice interfat˘ A la orice interfat˘ B. a a a • de la orice tip clas˘ A la orice interfat˘ B. atˆt AE cˆt ¸i BE sunt tipuri referint˘. INSTRUCTIUNI. exist˘ o conversie implicit˘ de tip referint˘ de la AE la BE a a ¸a • de la un tablou la System. ulong. decimal. double. dac˘ B este derivat din A. ¸a ¸a a a • de la orice tip tablou A cu tipul AE la un tip tablou B avˆnd tipul BE .Delegate.2. Alte conversii numerice implicite niciodat˘ a a nu duc la pierdere de informatie. ulong la float. float. • de la ulong la float. s s a 2. uint. A ¸i B au acela¸i num˘r de dimensiuni. double. pag. CLASE. Conversiile de la int. ulong. SPATII DE NUME ¸ ¸ • de la uint la long. ¸ Conversiile de tip enumerare implicite O astfel de conversie permite ca literalul 0 s˘ fie convertit la orice tip a enumerare (chiar dac˘ acesta nu contine valoarea 0) . a ¸a . int. • de la tipul null la orice variabil˘ de tip referint˘. • de la float la double. • de la tip delegat la System. ¸a • de la orice tip clas˘ B la orice tip clas˘ A. Conversii implicite de referinte ¸ Conversiile implicite de referinte implicite sunt: ¸ • de la orice tip referint˘ la object. dar niciodat˘ la o a reducere a ordinului de m˘rime. uint. a ¸ 29. a cu urm˘toarele conditii: a ¸ 1. • de la orice tip tablou sau tip delegat la System. dac˘ A implementeaz˘ B. long. a a s ¸a 3.a se vedea 2. decimal. precum ¸i cele de la long s sau ulong la double pot duce la o pierdere a preciziei.3.ICloneable.

4. a ¸ a ın 3.3.3 Conversii explicite Urm˘toarele conversii sunt clasificate ca explicite: a • toate conversiile implicite • conversiile numerice explicite • conversiile explicite de enumer˘ri a • conversiile explicite de referinte ¸ • unboxing • conversii explicite definite de utilizator Din cauz˘ c˘ orice conversie implicit˘ este de asemenea ¸i una explicit˘. urmat˘ de executia a ¸ a a ¸ unui operator de conversie implicit˘ utilizator urmat˘ de alt˘ conversie ima a a plicit˘ standard optional˘. O descriere mai am˘nuntit˘ este dat˘ ˆ sectiunea 3.3. short.3. uint.2 Conversiile implicite ale expresiilor constante Permit urm˘toarele tipuri de conversii: a • o expresie constant˘ de tip int poate fi convertit˘ c˘tre tipurile sbyte.3.//(long) este redundant . long y = (long)x.ValueType sau c˘tre orice tip interfat˘ pe care tipul valoare ˆ implea ¸a ıl menteaz˘. a a ¸ a a ın ¸ 3. CONVERSII Conversie de tip boxing 57 Permite unui tip valoare s˘ fie implicit convertit c˘tre tipul object sau a a System. dac˘ a a a valoarea ce se converte¸te nu este negativ˘. a a a s a aplicarea operatorului de cast este redundant˘: a int x = 0. ushort.3. Regulile exacte sunt descrise ˆ [4]. s a Conversii implicite definite de utilizator Constau ˆ ıntr–o conversie implicit˘ standard optional˘. a ın ¸ • o expresie constant˘ de tip long poate fi convertit˘ la tipul ulong. a a a byte. ulong. cu conditia ca valoarea expresiei con¸ stante s˘ se afle ˆ domeniul tipului destinatie.

• de la double la sbyte. int. ushort. char. ushort. exist˘ a ın a ¸ a dou˘ contexte ˆ care se fac aceste conversii: checked ¸i unchecked. int. a ın s ˆ context checked. short. • de la ulong la sbyte. uint. float.58 CURS 3. char. int. 115–116). int. int. char. byte. SPATII DE NUME ¸ ¸ Conversii numerice explicite Sunt conversii de la orice tip numeric la un alt tip numeric pentru care nu exist˘ conversie numeric˘ implicit˘: a a a • de la sbyte la byte. ulong. • de la short la sbyte. se va arunca exceptia Sysın ¸ tem. ushort. byte. double. byte. char. uint. ushort. CLASE. pag. short. INSTRUCTIUNI. short. • de la byte la sbyte. char. long. short. uint. uint. ushort. ˆ s a a a In cazul ˆ care conversia nu se poate face cu succes. ulong. long. byte. short. byte. ulong. Conversii explicite de enumer˘ri a Conversiile explicite de enumer˘ri sunt: a • de la sbyte. ushort. byte. decimal la orice tip enumerare. uint. byte. Pentru c˘ ˆ astfel de conversii pot ap˘rea pierderi de informatie. short. ushort. ulong. byte. byte. char. ulong. double. decimal. char. ushort. char. conversia se face ˆ In ıntotdeauna. • de la long la sbyte. ushort. short. • de la int la sbyte. ulong. ushort. long. decimal. float. • de la char la sbyte. short. short. ulong. byte. uint. conversia se face cu succes dac˘ valoarea care se conIn a verte¸te este reprezentabil˘ de c˘tre tipul c˘tre care se face conversia. char.OverflowException. uint. uint. • de la decimal la sbyte. int. float. • de la float la sbyte. long. ulong. • de la uint la sbyte. uint. ˆ context unchecked. char. • de la ushort la sbyte. dar se poate ajunge la pierdere de informatie sau la valori ce nu sunt bine ¸ nedefinite (vezi [4]. int. long. . byte. char. int. long. short.

• de la orice tip enumerare la orice tip enumerare. short. a • de la orice tip clas˘ A la orice tip interfat˘ B. s s a 2. A ¸i B au acela¸i num˘r de dimensiuni. Acest tip de conversii cer verificare la run–time.3. Dac˘ o astfel de conversie a e¸ueaz˘. ulong. uint.InvalidCastException. ushort.3. se va arunca o exceptie de tipul System.Delegate ¸i interfetele pe care le implementeaz˘ la orice s ¸ a tip delegat. long. • de la un tip tablou A cu elemente de tip AE la un tip tablou B cu elemente BE . as a • de la orice tip interfat˘ A la orice tip clas˘ B. Conversiile de tip enumerare se fac prin tratarea fiec˘rui tip enumerare a ca fiind tipul ˆ ıntreg de reprezentare. ¸a • de la orice tip clas˘ A la orice tip clas˘ B. Conversii explicite de referinte ¸ Conversiile explicite de referinte sunt: ¸ • de la object la orice tip referint˘. char. byte. s ¸a 3. a ¸ a • de la orice tip interfat˘ A la orice tip interfat˘ B. CONVERSII 59 • de la orice tip enumerare la sbyte. exist˘ o conversie de referint˘ explicit˘ de la AE al BE a ¸a a • de la System. invers.Array ¸i interfetele pe care le implementeaz˘ la orice tip s ¸ a tablou. s a ¸ . decimal. double. float. AE ¸i BE sunt tipuri referint˘. dac˘ B nu este nederiv¸a a a abil˘ sau cu conditia ca B s˘ implementeze A. se va face o conversie explicit˘ de la int la byte. int. cu conditiile: ¸ 1. dac˘ A nu este derivat ¸a ¸a a din B. dup˘ care se efectueaz˘ o conversie a a implict˘ sau explicit˘ ˆ a a ıntre tipuri (ex: dac˘ se dore¸te conversia de la un tip a s enumerare E care are tipul de reprezentare int la un tip byte. cu conditia ca A s˘ fie clas˘ a a ¸ a a de baz˘ pentru B. se va face o conversie implict˘ de a a la byte la int). • de la System. dac˘ A nu este nederiva ¸a a abil˘ ¸i A nu implementeaz˘ pe B.

tipul int (alias System.Int32) este derivat din clasa System. CLASE. urmat˘ de o alt˘ conversie standard explicit˘ optional˘.3. a a ¸a Boxing–ul unei valori const˘ ˆ alocarea unei variabile de tip obiect ¸i copierea a ın s valorii initiale ˆ acea instant˘.Object). Spre deosebire de Java.60 Unboxing CURS 3. } } Astfel. object box = i. ¸ ın ¸a Procesul de boxing al unei valori sau variabile de tip valoare se poate ˆ ¸elege ca o simulare de creare de clas˘ pentru acel tip: ınt a sealed class T_Box { T value. unde a exist˘ tipuri primitive (care nu pot contine metode) ¸i tipuri referint˘. Mai multe detalii se vor da ˆ sectiunea 3. Boxing Conversia de tip boxing permite oric˘rui tip valoare s˘ fie implicit convera a tit c˘tre tipul object sau c˘tre un tip interfat˘ implementat de tipul valoare. .ValueType a la orice tip valoare. ˆ C# a ¸ s ¸a ın toate tipurile sunt derivate din clasa object (alias System. a ¸a ın ¸ Conversii explicite definite de utilizator Constau ˆ ıntr–o conversie standard explicit˘ optional˘.4.ValueType care la rˆndul ei este derivat˘ din clasa object (alias System. public T_Box(T t) { value = t. Ca a a atare.3. INSTRUCTIUNI. declaratiile: ¸ int i = 123.4 Boxing ¸i unboxing s Boxing–ul ¸i unboxing–ul reprezint˘ modalitatea prin care C# permite s a utilizarea simpl˘ a sistemului unificat de tipuri. a a a ¸ a 3. orice int este compatibil cu object. SPATII DE NUME ¸ ¸ Unboxing-ul permite o conversie explicit˘ de la object sau System. sau de la orice tip interfat˘ la orice tip valoare care im¸a plementeaz˘ tipul interfat˘. urmat˘ de executia a ¸ a a ¸ unei conversii explicite.Object). De exemplu.

3.1: Boxing ¸i unboxing s Determinarea tipului pentru care s–a f˘cut ˆ a ımpachetarea se face prin intermediul operatorului is: int i = 123. o). ın ca ˆ linia 3. } Boxing–ul duce la o clonare a valorii care va fi continut˘. if (o is int) { Console. object box = new int_Box(i).//linia 1 object o = i. object o = i. care va contine valoarea 10. cˆt ¸i o informatie despre tipul de dat˘ continut ¸ a a s ¸ a ¸ (ˆ cazul nostru.1: la linia 1.WriteLine("in o: {0}". object o = i. i++.Int32 Figura 3.//linia 3 61 procesul se desf˘¸oar˘ ca ˆ figura 3. ın i 10 o 10 j 10 System. ¸ a secventa: ¸ int i = 10. La linia 2 se va crea o referint˘ o c˘tre un obiect alocat ˆ heap. se declar˘ ¸i se initializeaz˘ as a ın as ¸ a o variabil˘ de tip valoare. Pentru secventa: ¸ int i = 10. s a Altfel spus. care a ¸a a ın va contine atˆt valoarea 10. CONVERSII corespund conceptual la: int i = 123.Write("Este un int inauntru!!!!"). Console.//linia 2 int j = (int)o. System. va afi¸a valoarea nealterat˘ 10. .Int32). valoarea va fi stocat˘ a ¸ a pe stiv˘.3. Unboxing–ul se face printr–un cast explicit.

x mai este declarat //in blocul continator int z = x + y. } } .//eroare.f(). SPATII DE NUME ¸ ¸ 3. pentru varis ın ¸ abile se poate specifica valoarea initial˘.5 Declaratii de variabile ¸i constante ¸ s Variabilele ¸i constantele trebuie declarate ˆ C#. Ea este vizibil˘ ˆ ˆ a ¸ a ın ıntregul bloc ¸i toate sub-blocurile continute.1. y. Optional.3.62 CURS 3. y nu are o valoare definita asignata } } Constantele au valori initiale care trebuie s˘ se poat˘ evalua la compilare. CLASE.//eroare. iar pentru constante acest lucru este ¸ a obligatoriu. ˆ cazul ˆ care este declarat˘ ˆ interiorul unei a a ın ın a ın metode. Este o eroare ca ˆ ıntr–un sub-bloc s˘ se declare o variabil˘ cu acela¸i a a s nume ca ˆ blocul contin˘tor: ın ¸ a void F() { int x = 3. ¸ a a 3. myLabel: return x. INSTRUCTIUNI. } static void Main() { DemoLabel dl = new DemoLabel().3.//ok { string x = "Mesaj: ". dl. O variabil˘ trebuie s˘ aib˘ valoarea asignat˘ definit˘ ˆ a a a a a ınainte ca valoarea ei s˘ fie utilizat˘. O etichet˘ poate fi referit˘ de c˘tre s ¸ a a a o instructiune goto: ¸ class DemoLabel { int F(int x) { if (x >= 0) goto myLabel.//ok const double d = 1.6 Declaratii de etichete ¸ O etichet˘ poate prefixa o instructiune. x = -x.

3.3. CONVERSII

63

3.3.7

Instructiuni de selectie ¸ ¸

Instructiunea if ¸ Instructiunea if execut˘ o instructiune ˆ functie de valoarea de adev˘r a ¸ a ¸ ın ¸ a unei expresii logice. Are formele: if (expresie logica) instructiune; if (expresie logica) instructiune; else instructiune; Instructiunea switch ¸ Permite executarea unei instructiuni ˆ functie de valoarea unei expresii, ¸ ın ¸ care se poate reg˘si sau nu ˆ a ıntr–o list˘ de valori candidat: a switch (expresie) { case eticheta: instructiune; case eticheta: instructiune; ... default: instructiune; } O etichet˘ reprezint˘ o expresie constant˘. O instructiune poate s˘ ¸i lipseasc˘ a a a ¸ as a ¸i ˆ acest caz se va executa instructiunea de la case–ul urm˘tor, sau de la des ın ¸ a fault. Sectiunea default poate s˘ lipseasc˘. Dac˘ o instructiune este nevid˘, ¸ a a a ¸ a atunci obligatoriu va avea la sfˆr¸it o instructiune break sau goto case expreas ¸ sieConstanta sau goto default. Expresia dup˘ care se face selectia poate fi de tip sbyte, byte, short, ushort, a ¸ int, uint, long, ulong, char, string, enumerare. Dac˘ valoarea expresiei se a reg˘se¸te printre valorile specificate la clauzele case, atunci instructiunea a s ¸ corespunz˘toare va fi executat˘; dac˘ nu, atunci instructiunea de la clauza a a a ¸ default va fi executat˘ (dac˘ ea exist˘). Spre deosebire de C ¸i C++, e interzis a a a s s˘ se foloseasc˘ fenomenul de ”c˘dere” de la o etichet˘ la alta; continuarea a a a a se face folosind explicit goto. Subliniem c˘ se permite folosirea unui selector a de tip string. switch (i) { case 0: Console.WriteLine("0"); break; case 1:

64

CURS 3. CLASE, INSTRUCTIUNI, SPATII DE NUME ¸ ¸ Console.Write("Valoarea "); goto case 2; case 2: case 3: Console.WriteLine(i); break; case 4: goto default; default: Console.WriteLine("Numar in afara domeniului admis"); break;//neaparat, altfel eroare de compilare

} Remarc˘m ˆ exemplul de mai sus c˘ chiar ¸i ˆ cazul lui default e necesar a ın a s ın s˘ se foloseasc˘ instructiune de salt (ˆ cazul nostru break ); o motivatie ar fi a a ¸ ın ¸ c˘ aceast˘ clauz˘ default nu e necesar s˘ fie trecut˘ ultima ˆ switch, ci chiar a a a a a ın ¸i pe prima pozitie – desigur caz mai rar ˆ alnit. s ¸ ıntˆ Exist˘ un caz ˆ care break, goto case valoare sau goto default pot s˘ a ın a lipseasc˘: cˆnd este evident c˘ o asemenea instructiune break/goto nu ar a a a ¸ putea fi atins˘ (i.e. sunt prezente instructiunile return, throw sau o ciclare a ¸ despre care se poate afirma la compilare c˘ este infinit˘). a a

3.3.8

Instructiuni de ciclare ¸

Exist˘ 4 instructiuni de ciclare: while, do, for, foreach. a ¸ Instructiunea while ¸ Permite executarea unei instructiuni atˆta timp cˆt valoarea unei expresii ¸ a a logice este adev˘rat˘ (ciclu cu test anterior). a a Sintaxa: while (expresie logica) instructiune; ˆ interiorul unei astfel de instructiuni se poate folosi o instructiune de salt In ¸ ¸ de tip break sau continue. while { r = a = b = } (r != 0) a%b; b; a;

3.3. CONVERSII Instructiunea do ¸

65

Execut˘ o instructiune o dat˘ sau de mai multe ori, cˆt timp o conditie a ¸ a a ¸ logic˘ este adev˘rat˘ (ciclu cu test posterior). a a a Exemplu: do { S += i++; }while(i<=n) Poate contine instructiuni break sau continue. ¸ ¸ Instructiunea for ¸ Execut˘ o secvent˘ de initializare, dup˘ care va executa o instructiune a ¸a ¸ a ¸ atˆta timp cˆt o conditie este adev˘rat˘ (ciclu cu test anterior); poate s˘ a a ¸ a a a contin˘ un pas de reinitializare (trecerea la pasul urm˘tor). Se permite ¸ a ¸ a folosirea instructiunilor break ¸i continue. ¸ s Exemplu: for (int i=0; i<n; i++) { Console.WriteLine("i={0}", i); } Instructiunea foreach ¸ Enumer˘ elementele dintr–o coletie, executˆnd o instructiune pentru fiecare a ¸ a ¸ element. Colectia poate s˘ fie orice instant˘ a unei clase care implementeaz˘ ¸ a ¸a a interfata System.Collections.IEnumerable. ¸ Exemplu: int[] t = {1, 2, 3}; foreach( int x in t) { Console.WriteLine(x); } Elementul care se extrage este de tip read–only (deci nu poate fi transmis ca parametru ref sau out ¸i nu se poate aplica un operator care s˘ ˆ schimbe s a ıi valoarea).

66

CURS 3. CLASE, INSTRUCTIUNI, SPATII DE NUME ¸ ¸

3.3.9

Instructiuni de salt ¸

Permit schimbarea ordinii de executie a instructiunilor. Ele sunt: break, ¸ ¸ continue, goto, return, throw. Instructiunea break ¸ Produce ie¸irea fortat˘ dintr–un ciclu de tip while, do, for, foreach. s ¸ a Instructiunea continue ¸ Porne¸te o nou˘ iteratie ˆ interiorul celui mai apropiat ciclu contin˘tor s a ¸ ın ¸ a de tip while, do, for, foreach. Instructiunea goto ¸ Goto permite saltul al o anumit˘ instructiune. Are 3 forme: a ¸ goto eticheta; goto case expresieconstanta; goto default; Cerinta este ca eticheta la care se face saltul s˘ fie definit˘ ˆ cadrul functiei ¸ a a ın ¸ curente ¸i saltul s˘ nu se fac˘ ˆ interiorul unor blocuri de instructiuni, s a a ın ¸ deoarece nu se poate reface ˆ ıntotdeauna contextul acelui bloc. Se recomand˘ evitarea utiliz˘rii intense a acestui cuvˆnt cheie, ˆ caz cona a a ın trar se poate ajunge la fenomenul de ”spagetti code”. Pentru o argumentare consistent˘ a acestei indicatii, a se vedea articolul clasic al lui Edsger W. Dijka ¸ stra, ”Go To Statement Considered Harmful”: http://www.acm.org/classics/oct95/ Instructiunea return ¸ Determin˘ cedarea controlului funtiei apelante de c˘tre functia apelat˘. a ¸ a ¸ a Dac˘ functia apelat˘ are tip de retur, atunci instructiunea return trebuie a ¸ a ¸ s˘ fie urmat˘ de o expresie care suport˘ o conversie implicit˘ c˘tre tipul de a a a a a retur.

3.3.10

Instructiunile try, throw, catch, finally ¸

Permit tratarea exceptiilor. Vor fi studiate ˆ detaliu la capitolul de ¸ ın exceptii. ¸

3.3. CONVERSII

67

3.3.11

Instructiunile checked ¸i unchecked ¸ s

Controleaz˘ contextul de verificare de dep˘¸ire a domeniului pentru arita as metica pe ˆ ıntregi ¸i conversii. Au forma: s checked { //instructiuni } unchecked { //instructiuni } Verificare se va face la run–time.

3.3.12

Instructiunea lock ¸

Obtine excluderea mutual˘ asupra unui obiect pentru executarea unui ¸ a bloc de instructiuni. Are forma: ¸ lock (x) instructiuni X trebuie s˘ fie de tip referint˘ (dac˘ este de tip valoare, nu se face boxing). a ¸a a

3.3.13

Instructiunea using ¸

Determin˘ obtinerea a unei sau mai multor resurse, execut˘ o instructiune a ¸ a ¸ ¸i apoi disponibilizeaz˘ resursa: s a using ( achizitie de resurse ) instructiune O resurs˘ este o clas˘ sau o structur˘ care implementeaz˘ interfata System.Ia a a a ¸ Disposable, care include o sigur˘ metod˘ f˘r˘ parametri Dispose(). Achizitia a a aa ¸ de resurse se poate face sub form˘ de variabile locale sau a unor expresii; toate a acestea trebuie s˘ fie implicit convertibile la IDisposable. Variabilele locale a alocate ca resurse sunt read–only. Resursele sunt automat dealocate (prin apelul de Dispose) la sfˆr¸itul instructiunii (care poate fi bloc de instructiuni). as ¸ ¸ Motivul pentru care exist˘ aceast˘ instructiune este unul simplu: uneori a a ¸ se dore¸te ca pentru anumite obiecte care detin resurse importante s˘ se s ¸ a apeleze automat metod˘ Dispose() de dezalocare a lor, cˆt mai repede cu a a putint˘. ¸a Exemplu:

class Test { static void Main() { using( TextWriter w = File. dar responsabilit˘¸i diferite. Solutia la aceast˘ a a ın ¸ a 4 problem˘ este crearea spatiilor de nume care rezolv˘. un spatiu ¸ ¸ de nume este o colectie de tipuri sau de alte spatii de nume.CreateText("log.4 Spatii de nume ¸ ˆ cazul cre˘rii de tipuri este posibil s˘ se foloseasc˘ un acela¸i nume In a a a s pentru tipurile noi create de c˘tre dezvoltatorii de soft.EriteLine("This is line 2"). INSTRUCTIUNI. ¸ Crearea unui spatiu de nume se face prin folosirea cuvˆntului namespace: ¸ a using System. treat buie prev˘zut˘ o modalitate de a le adresa ˆ mod unic.txt") ) { w. Altfel spus. } } } 3. putem folosi de exemplu clasa Buffer din a at spatiul System (calificare complet˘: System.Buffer. } } } Se pot de asemenea crea spatii de nume imbricate. SPATII DE NUME ¸ ¸ using System. Pentru a putea a folosi astfel de clase care au numele comun. Astfel.68 CURS 3.IO. ¸ ¸ 4 engl: namespaces . CLASE.Buffer). using System.WriteLine("Bufferul meu!"). namespace Curs3 { public class Buffer { public Buffer() { Console. al˘turi de clasa Buffer ¸ a a din spatiul de nume Curs3: Curs3. w. printr–o adresare coma ¸ a plet˘ astfel de ambiguit˘¸i.WriteLine("This is line 1").

pentru a se evita calificarea complet˘ a claselor. a Identificatorul unui spatiu de nume poate fi simplu sau o secventa de ¸ ¸˘ identificatori separati prin ”. urmat ¸ ¸ a ın a de identificatorul spatiului de nume ¸i de blocul spatiului de nume. Cea de a doua form˘ permite definirea de ¸ a spatii de nume imbricate.1 Declaratii de spatii de nume ¸ ¸ O declaratie de spatiu de nume const˘ ˆ cuvˆntul cheie namespace. a a ¸ .4.4.”.N2 { class A{} } namespace N1. Spatiile de nume sunt implicit publice ¸i acest tip de acces nu se ¸ s poate modifica. f˘r˘ a se imbrica efectiv: ¸ aa namespace N1.N2 { class B{} } este echivalent˘ cu cele dou˘ declaratii anterioare. delimitat ¸ s ¸ de acolade. SPATII DE NUME ¸ 69 3. ˆ interiorul unui spatiu de nume se pot utiliza alte spatii In ¸ ¸ de nume.3.N2 { class A{} class B{} } este echivalent˘ cu: a namespace N1 { namespace N2 { class A{} class B{} } } Dou˘ declaratii de spatii de nume cu aceea¸i denumire contribuie la a ¸ ¸ s declararea unui acela¸i spatiu de nume: s ¸ namespace N1.

. i.2 Directiva using Directiva using faciliteaz˘ ˆ primul rˆnd utilizarea spatiilor de nume ¸i a a ın a ¸ s tipurilor definite ˆ acestea. ele nu creeaz˘ membri noi ˆ cadrul unit˘¸ii de ın a ın at program ˆ care sunt folosite. folosirea lor f˘r˘ a fi necesar˘ o calificare ¸ aa a complet˘. } } decˆt: a class A { static void Main() { System. class A { static void Main() { Console. structurilor.WriteLine("Mesaj").WriteLine("Mesaj"). } } Directiva using poate fi de fapt folosit˘ atˆt pentru importuri simbolice. INSTRUCTIUNI.e. SPATII DE NUME ¸ ¸ 3. Nu se ın s pot utiliza ˆ interiorul claselor. a s Directiva using pentru import simbolic O directiv˘ using permite importarea simbolic˘ a tuturor tipurilor continute a a ¸ direct ˆ ıntr–un spatiu de nume. ci au rol de a u¸ura referirea tipurilor.N2 { class A{} } namespace N3.N4 { class B{}. Acest import nu se refer˘ ¸i la spatiile de nume continute: a as ¸ ¸ namespace N1.4.70 CURS 3. a a cˆt ¸i pentru crearea de aliasuri. CLASE. ın a Exemplu: e mai u¸or de ˆ s ınteles un cod de forma: using System.Console. enumer˘ririlor.

class C { A a = null.N2. N4 nu a fost importat } } Importarea de spatii de nume nu trebuie s˘ duc˘ la ambiguit˘¸i: ¸ a a at namespace N1 { class A{} } namespace N2 { class A{} } namespace N3 { using N1. using N2. conflictul (care poate foarte u¸or ˆ cazul ˆ care se In ¸ s ın ın folosesc tipuri produse de dezvoltatori diferiti) poate fi rezolvat de o calificare ¸ complet˘: a namespace N3 { using N1. SPATII DE NUME ¸ } namespace N5 { using N1.//Eroare. class B { .//ok N4.3.A? } } 71 ˆ situatia de mai sus. using N3.4. class B { A a = null.//ambiguitate: N1.B = null. using N2.A sau N2.

nu mai este ambiguitate } } Tipurile declarate ˆ interiorul unui spatiu de nume pot avea modificatori de ın ¸ acces public sau internal (modificatorul implicit).72 CURS 3.A a2 = null. class B { N. ın a Directiva using ca alias Introduce un identificator care serve¸te drept alias pentru un spatiu de s ¸ nume sau pentru un tip. pe cˆnd unul public. N2.//ok. class B { A a = null.N2: s ¸ ınd ¸ namespace N3 { using N = N1. Un tip internal nu poate fi folosit prin import ˆ afara assembly-ului. Exemplu: namespace N1.A. } } Identificatorul dat unui alias trebuie s˘ fie unic.A a1 = null.A a = null. SPATII DE NUME ¸ ¸ N1. adic˘ ˆ interiorul unui a a ın namespace nu trebuie s˘ existe tipuri ¸i aliasuri cu acela¸i nume: a s s . INSTRUCTIUNI. } } Acela¸i efect se obtine creˆ un alias la spatiul de nume N1.N2. CLASE.N2. da.N2 { class A{} } namespace N3 { using A = N1.

//eroare.A. Situatia de mai sus se poate rezolva a a ¸ prin declarearea aliasului ˆ afara spatiului de nume: ın ¸ using R = namespace { class B { R.N2.A b } } N1.N2.A a } } N3 = N1. SPATII DE NUME ¸ 73 namespace N3 { class A{} } namespace N3 { using A = N1.4. R nu este definit aici adic˘ directiva de alias nu este tranzitiv˘.//eroare. N3 = null. N3 = null.A a } } namespace { class C { R. N3 = null.3. Numele create prin directive de alias sunt ascunse de c˘tre alte declaratii a ¸ care folosesc acela¸i identificator ˆ interiorul unui bloc: s ın .N2. deoarece simbolul A mai este definit } O directiv˘ alias afecteaz˘ doar blocul ˆ care este definit˘: a a ın a namespace { using R } namespace { class B { R.

R1 necunoscut } .N2. using R2 = N1.A a.N2.N2{} namespace N3 { using R1 = N1. INSTRUCTIUNI. CLASE.//eroare. clasa R nu are membrul A } } Directivele de alias nu se influenteaz˘ reciproc: ¸ a namespace N1. SPATII DE NUME ¸ ¸ using R = N1.//eroare. namespace N3 { class R{} class B { R.N2. using R3 = R1.74 CURS 3.

Semnific˘ acces permis ¸ ın ¸ a doar ˆ clasa sau spatiul de nume care o cuprinde. este modificatorul implicit. internal . ¸ a new . a a ¸ private .clasele publice sunt accesibile de oriunde. poate fi folosit atˆt pentru a clase interioare. ın ¸ protected . s s 75 . cˆt ¸i pentru clase care sunt continute ˆ spatii de a s ¸ ın ¸ nume.opt Modificatorii de clas˘ sunt: a public . cˆt ¸i pentru clase care a a s sunt continute ˆ spatii de nume (este modificatorul implicit pentru ¸ ın ¸ clase care sunt continute ˆ spatii de nume).se poate specifica doar pentru clase interioare.folosibil doar pentru clase interioare.Curs 4 Clase 4. semnific˘ acces limitat la clasa cona ¸in˘toare.doar pentru clase interioare.permis pentru clasele interioare. clasa astfel calificat˘ ascunde un a membru cu acela¸i nume care este mo¸tenit.se poate folosi atˆt pentru clase interioare. tipul definit este accesibil ˆ spatiul de nume curent.1 Declararea unei clase Declararea unei clase se face ˆ felul urm˘tor: ın a atributeopt modificatori-de-clasaopt class identificator clasa-de-bazaopt corpclasa . tipurile astfel calificate sunt accesibile ˆ clasa curent˘ sau ˆ cele derivate (chiar ın a ın dac˘ clasa derivat˘ face parte din alt spatiu de nume). t a protected internal . ˆ clasa contin˘toare sau ˆ tipurile ın ¸ ın ¸ a ın derivate din clasa contin˘toare.

membrul este accesabil doar ˆ assembly-ul curent. ın ¸ a . s a internal . poate fi clas˘ interioar˘ sau a s a a a nu. protected .reuniunea precedentelor dou˘. CLASE sealed . ın protected internal . a private accesabil doar ˆ clasa contin˘toare.opt Membrii unei clase sunt ˆ artiti ˆ urm˘toarele categorii: ımp˘ ¸ ın a • constante • cˆmpuri a • metode • propriet˘¸i at • evenimente • indexatori • operatori • constructori (de instant˘) ¸a • destructor • constructor static • tipuri Acestor membri le pot fi ata¸ati modificatorii de acces: s ¸ public . este specificatorul implicit. abstract . as ¸ a folosibil˘ pentru clase interioare sau continute ˆ spatii de nume.2 Membrii unei clase Corpul unei clase se specific˘ ˆ felul urm˘tor: a ın a { declaratii-de-membri }.membrul este accesibil de oriunde. a ¸ ın ¸ 4.membrul este accesabil de c˘tre orice membru al clasei contin˘toare a ¸ a ¸i de c˘tre clasele derivate.o clas˘ sealed nu poate fi mo¸tenit˘.clasa care este incomplet definit˘ ¸i care nu poate fi instantiat˘.76 CURS 4.

Optional. a ce vor fi prezentati mai jos.2 Cˆmpuri statice a Cˆnd o declaratie de cˆmp include un specificator static. fie printr-o a a calificare bazat˘ pe numele clasei sau al unui obiect. objA. volatile. la care se adaug˘ modificatorii new. readonly. a Exemplu: class A { int a. cˆmpul respectiv a ¸ a a nu apatine fiec˘rei instante ˆ particular.a = 1. a a Deoarece un astfel de cˆmp are o valoare specific˘ fiec˘rui obiect.//acces implicit de tip privat static void Main() { A objA = new A().1 Cˆmpuri instante a ¸ Dac˘ o declaratie de cˆmp nu include modificatorul static. 4.3.a = 1. atunci acel a ¸ a cˆmp se va reg˘si ˆ orice obiect de tipul clasei curente care va fi instantiat. Accesarea unui ¸ a ¸ ın ıns˘s cˆmp static din exteriorul clasei se face exclusiv prin intermediul numelui de a clas˘: a .ˆ 4. a a ın ¸ Modific˘ri ale acestor cˆmpuri se vor face independent pentru fiecare obiect. accesarea a a a lui se va face prin calificarea cu numele obiectului: objA.3. a s Un cˆmp special este this (cuvˆnt cheie) care reprezint˘ o referint˘ la a a a ¸a obiectul curent.3. a a a Modificatorii de cˆmp care se pot specifica optional ˆ a ¸ ınaintea unui cˆmp sunt a cei de mai sus. ce trebuie s˘ aibe gradul de accesibilitate cel putin cu al cˆmpului a ¸ a ce se declar˘. a ¸ a ¸ Un astfel de cˆmp se poate folosi fie prin specificarea numelui s˘u. ci clasei ˆ a¸i. cˆmpurile pot fi initializate cu valori compatibile.3 Cˆmpuri a Un cˆmp reprezint˘ un membru asociat cu un obiect sau cu o clas˘. static. CAMPURI 77 4. Pentru orice cˆmp este necesar˘ precizarea unui ¸ a a tip de date.//se poate accesa in interiorul clasei } } 4. (dac˘ modificatorii de acces permit a¸a ceva).

char.V++. ushort. sbyte. public readonly string nume. • un tip referint˘ ¸a . float. static void Main() { B. • un tip enumerare avˆnd tipul de reprezentare byte. Valoarea ın unor astfel de cˆmpuri nu se presupune a fi cunoscut˘ la compilare. int.nume = nume. short. CLASE Dac˘ se face calificarea unui astfel de cˆmp folosind un nume de obiect se a a semnaleaz˘ o eroare de compilare. a 4. a a 4.3 Cˆmpuri readonly a Declararea unui cˆmp de tip readonly (static sau nu) se face prin specifia carea cuvˆntului readonly ˆ declaratia sa: a ın ¸ class A { public readonly string salut = ‘‘Salut’’. a int.4 Cˆmpuri volatile a Modificatorul ”volatile” se poate specifica doar pentru tipurile: • byte. uint. ushort.3. public class A(string nume) { this. uint. } } Atribuirea asupra unui cˆmp de tip readonly se poate face doar la declararea a sa (ca ˆ exemplu de mai sus) sau prin intermediul unui constructor. bool.3. } } CURS 4. sbyte. short.78 class B { public static int V = 3.

de c˘tre sistemul a a a a 1 de rulare sau de c˘tre hardware. CONSTANTE 79 Pentru cˆmpuri nevolatile. internal. a a a protected. a a • orice scriere a unui cˆmp volatile este garantat˘ c˘ se va petrece dup˘ a a a a orice instructiune anterioar˘ care se refer˘ la cˆmpul respectiv.5 Initializarea cˆmpurilor ¸ a Pentru fiecare cˆmp declarat se va asigna o valoare implicit˘ astfel: a a • numeric: 0 • bool: false • char: ‘\0’ • enum: 0 • referint˘: null ¸a 4.4. protected internal. ¸ a a a 4. Urm˘toarele tipuri de optimiz˘ri sunt a a a afectate ˆ prezenta unui modificator volatile: ın ¸ • citirea unui cˆmp volatile este garantat˘ c˘ se va ˆ ampla ˆ a a a ıntˆ ınainte de orice referire la cˆmp care apare dup˘ citire. O constant˘ poate fi prefixat˘ de urm˘torii modificatori: new. Cuvantul new poate s˘ se coma bine cu unul din ceilalti 4 modificatori de acces. } 1 Engl: runtime system . public.4.4 Constante O constant˘ este un cˆmp a c˘rui valoare poate fi calculat˘ la compia a a a lare. tehnicile de optimizare care reordoneaz˘ instructiunile a a ¸ pot duce la rezultate nea¸teptate sau nepredictibile ˆ programe multithreads ın ing care acceseaz˘ cˆmpurile f˘r˘ sincronizare (efectuabil˘ cu instructiunea a a aa a ¸ lock). Aceste optimiz˘ri pot fi f˘cute de c˘tre compilator.3.private. Pentru un cˆmp constant e ¸ a obligatoriu s˘ se asigneze o valoare calculabil˘ la compilare: a a class A { public const int n=2.

Antetul unei metode a a a se declar˘ ˆ felul urm˘tor: a ın a atributeopt modificator-de-metodaopt tip-de-retur nume (lista-parametrilorformaliopt ) corp-metoda unde modificator-de-metoda poate fi: • orice modificator de acces • new • static • virtual • sealed • override • abstract • extern Tipul de retur poate fi orice tip de dat˘ care este cel putin la fel de accesibil a ¸ ca ¸i metoda ˆ a¸i sau void (absenta informatiei returnate). override. byte. uint. corpaa metoda este un bloc cuprins ˆ ıntre acolade sau doar caracterul “. nume poate fi un s ıns˘s ¸ ¸ identificator de metod˘ din clasa curent˘ sau un identificator calificat cu nua a mele unei interfete pe care o implementeaz˘ (NumeInterfata. a a ın Despre calificatorii virtual. Un cˆmp constant a a a difer˘ de un cˆmp static readonly: const-ul are o valoare cunoscut˘ la coma a a pilare. ¸ a parametrii pot fi de tip ref.” (dac˘ este a vorba de o metod˘ ce nu se implementeaz˘ ˆ tipul curent). bool. Tipul unei constante trebuie s˘ fie cel putin la fel de accesibil ca a ¸ ¸i constanta ˆ a¸i. ¸ . pe cˆnd valoarea unui readonly poate fi initializat˘ la runtime ˆ a ¸ a ın interiorul constructorului (cel mai tˆrziu. referint˘. enum. double decimal. a 4. string. s ıns˘s Orice cˆmp constant este automat un cˆmp static.numeMetoda). new. CLASE Tipul unei constante poate fi sbyte. sealed. abstract se va discuta mai pe larg ˆ ıntr–o sectiune viitoare. Valoarea care se ¸a asignez˘ unei constante trebuie s˘ admit˘ o conversie implicit˘ c˘tre tipul a a a a a constantei.80 CURS 4. ulong. out. ushort. params. float. de altfel). int. long.5 Metode O metod˘ este un membru care implementeaz˘ un calcul sau o actiune a a ¸ care poate fi efectuat˘ de c˘tre un obiect sau o clas˘. char. sau f˘r˘ nici un calificator. short.

Deoarece ın a o astfel de metod˘ nu contine o implementare. Ele sunt de fapt ni¸te metode (accesori) care permit citirea s sau setarea unor atribute ale unui obiect sau clase. cu deosebirea c˘ ele nu presupun aloa a carea de memorie. .dll: using System.5. Propriet˘¸ile at sunt extensii naturale ale cˆmpurilor. O astfel de metod˘ nu opereaz˘ asupra unei a a a instante anume. PROPRIETATI 81 4. 0).2 Metode externe Metodele externe se declar˘ folosind modificatorul extern. a s O metod˘ nestatic˘ nu are cuvˆntul “static” specificat. string m. "Caption". a ¸ Exemplu: se utilizeaz˘ metoda MessageBox importat˘ din biblioteca dll a a User32. textul continut ˆ ıntr–un control de tip TextBox. int type). ın ¸ 4. ea este apelabil˘ a a a a ˆ conjunctie cu un obiect anume. string c.dll")] public static extern int MessageBox(int h. de obicei ˆ alt limbaj decˆt C#.6.˘¸ 4.1 Metode statice ¸i nestatice s O metod˘ se declar˘ a fi static˘ dac˘ numele ei este prefixat cu moda a a a ificatorul de metod˘ static.”. acest tip de a metode sunt implementate extern. Exemple de propriet˘¸i sunt: lungimea unui ¸ir.NumeMetoda sau direct NumeMetoda dac˘ a este apelat˘ din context static al aceleia¸i clase.InteropServices.5. class Class1 { [DllImport("User32. "Hello". Este o eroare ca o metod˘ static˘ ¸ a a s˘ fac˘ referire la un membru nestatic al unei clase. corpul acestei metode este “. static void Main(string[] args) { int retVal = MessageBox(0. ci doar asupra clasei. Apelul unei astfel de a a metode se face prin NumeClasa.6 Propriet˘¸i at O proprietate este un membru care permite acces la un atribut al unui obiect sau al unei clase. using System. nuat s mele unui client. } } 4. reprezint˘ modalitatea a de scriere a unor metode de tip get/set pentru clase sau obiecte.Runtime.

PI).82 CURS 4.PI * radius * radius. class Circle { private double radius. protected. private. } set { radius = value. respectiv care este tipul valorii returnate de aceast˘ a proprietate (corespunz˘tor accesorului de tip get). virtual. } } public double Area { get { return Math. } set { radius = Math. public. sealed. } } } class Test { static void Main() . internal. abstract. ce valori vor putea fi atribuite propriet˘¸ii respective (dac˘ accesorul de at a tip set a fost definit).Sqrt(value/Math. Tipul unei propriet˘¸i specific˘ tipul de proprietate introdus de declaratie. static.e. CLASE Declararea unei propriet˘¸i se face astfel: at atributeopt modificatori-de-proprietateopt tip nume {declaratii-de-accesor} Modificatorii de proprietate sunt: new. public double Radius { get { return radius. a Exemplu: using System. extern. at a ¸ i. override.

Radius) } } 83 Un accesor de tip get corespunde unei metode f˘r˘ parametri. dac˘ este prezent doar accesorul de tip set. Acest parametru implicit al lui set at s este numit ˆ ıntotdeauna value.Area). c.6. dac˘ are doar accesor de tip get. System. c. dac˘ are ambele tipuri de accesori.1 este dat˘ reprezentarea unui control utilizator: In a Codul corespunz˘tor este dat mai jos: a using using using using using using System.WriteLine(‘‘Radius: {0}’’. a Un accesor de tip set corespunde unei metode cu un singur parametru de tipul propriet˘¸ii ¸i tip de retur void. care se face extrem de u¸or. accesorul get este o apelat pentru a returna valoarea cerut˘. o proprietate este clasifiIn ¸ ¸ ¸ cat˘ dup˘ cum urmeaz˘: a a a proprietate read–write.Forms. System. c. Cˆnd o proprietate este folosit˘ ca destinatar a a ˆ ıntr–o atribuire. System.˘¸ 4. a ¸ Demn de mentionat este c˘ ei pot fi folositi nu numai pentru a asigura ¸ a ¸ o sintax˘ simplu de folosit pentru metodele traditionale de tip get/set. PROPRIETATI { Circle c = new Circle().Radius = 10. .Data. Console.Windows. a ˆ functie de prezenta sau absenta accesorilor. a proprietate read–only.NET utilizator. s ˆ figura 4.WriteLine(‘‘Area: {0}’’. Cˆnd o proprietate este folosit˘ ˆ at a a ıntr–o expresie. este a o eroare de compilare utilizarea unei propriet˘¸i ˆ at ıntr–un context ˆ care ın ar fi necesar˘ prezenta accesorului get. System.Drawing.Collections. c. Console. ci ¸i a ¸ s pentru scrierea controalelor . care returneaz˘ aa a o valoare de tipul propriet˘¸ii. accesorului set i a s se transmite un parametru care reprezint˘ noua valoare. este o eroare de a compilare s˘ se fac˘ referire ˆ program la o proprietate ˆ sensul ˆ a a ın ın ın care s–ar cere operarea cu un accesor de tip set. sau cˆnd se folosesc operatorii ++ ¸i −−. proprietate write–only.Area = 15.ComponentModel. System.

Forms. private System.label1 = new System.Forms. private System.Dispose().Forms.Label label3. private System.Label(). InitializeComponent(). } protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.ComponentModel.Windows.TextBox phoneTextBox.84 CURS 4.Windows.Label label2.Forms Form Designer. } #region Component Designer generated code private void InitializeComponent() { this. private System.Forms.Dispose( disposing ).Windows.Forms.TextBox streetTextBox. } base. private System.Windows.Windows.Windows.1: Control definit de utilizator namespace UserControlSample { public class UserControl1 : System.Forms.Label label1.Windows. public UserControl1() { // This call is required by the Windows.TextBox numberTextBox.UserControl { private System.Forms. CLASE Figura 4.Windows. private System. .Forms.Container components = null.

AutoSize = true.label3. 44).Drawing.Point(56.Control[] { this.Size = new System. this.label1. this.Forms.Location = new System.numberTextBox.label1. 13). this. 79). this.Size(44.streetTextBox.6. this. this.label2.Point(8. this.Text = "". this.Label().Location = new System.Windows.label2 = new System.Drawing.AutoSize = true. 13).Point(56.Text = "Number".numberTextBox. this.˘¸ 4. this. this. this.phoneTextBox.Name = "label2".Drawing. 14). this. PROPRIETATI 85 this.AddRange(new System.Location = new System. this.Drawing. this.Forms. this.numberTextBox.phoneTextBox = new System.Windows.Drawing.streetTextBox. this. .Text = "".label1. this.label2. this.Name = "numberTextBox". 48).label2.Location = new System.Forms. this.Location = new System.TabIndex = 3.Forms. this.Name = "label1". this. this.Size = new System. this.phoneTextBox.Name = "label3".TextBox().label3.Point(8. this.label2.Forms.label2.Controls.TabIndex = 5.numberTextBox.streetTextBox.Drawing. this.Point(8.AutoSize = true.Forms.streetTextBox. this. this. this.label1.TabIndex = 1.Name = "streetTextBox".TextBox().Size(37. this.Windows. 13). this.label2.Windows.Windows.Name = "phoneTextBox".numberTextBox = new System.phoneTextBox.Drawing.label2.TabIndex = 0.phoneTextBox. this.Label().label3.label3.label3. this.Text = "". this.Text = "Street".Drawing.Drawing.label1. this.Windows. 75). this. 16).Point(56.label3. this. this.Size(34.TabIndex = 2.label3.label3 = new System.numberTextBox.TabIndex = 4.Text = "Phone".Size = new System.streetTextBox = new System.SuspendLayout().phoneTextBox.TextBox().label1. this.Location = new System.

} set{ phoneTextBox.Text.Name = "UserControl1". } #endregion [Category ("Data"). . Number ¸i Phone care vor at s fi vizibile ˆ fereastra Properties atunci cˆnd acest control va fi ad˘ugat la o ın a a form˘. cap.Text. this. } } [Category ("Data"). Description ("Contents of Number Control")] public string Number { get{ return numberTextBox. } set{ numberTextBox.streetTextBox. } } } } Interesante sunt aici propriet˘¸ile publice Street. Pentru mai multe detalii despre componente utilizator.Text.Size(168.Text = value.Text = value. Atributele cuprinse ˆ a ıntre paranteze drepte sunt optionale. } } [Category ("Data"). CLASE this.Text = value.Drawing. at a ın ¸ ¸i nu ˆ cea “Misc”. s ın a se vedea [1]. 112).Size = new System. this. } set{ streetTextBox. dar vor face ¸ ca aceste propriet˘¸i s˘ fie grupate ˆ sectiunea de date a ferestrei Properties.ResumeLayout(false). this.86 CURS 4. Description ("Contents of Phone Control")] public string Phone { get{ return phoneTextBox.label1}). this. Description ("Contents of Street Control")] public string Street { get{ return streetTextBox. 4.

¸ a a at Exemple: 1. Este o generalizare a supraˆ arc˘rii operatorului [] din C++. asem˘n˘tor cu cei de la propriet˘¸i.7. Lista parametrilor formali trebuie s˘ contin˘ cel putin un parametru ¸i nu a ¸ a ¸ s poate s˘ aibe vreun parametru de tip ref sau out. public MyVector( int length ) { v = new double[ length ]. Declaratorul de indexator are forma: tip-de-retur this[lista-parametrilor-formali]. Exemplul 1: un indexator simplu: using System. class MyVector { private double[] v.4. sealed. fiind o facilitate ce d˘ o mare ınc˘ a a flexibilitate. internal.7 Indexatori Uneori are sens tratarea unei clase ca fiind un array. } public int Length { get { return length. virtual. } } public double this[int index] { get { return v[ index]. protected. override. extern. public. INDEXATORI 87 4. private. Declararea unui indexator se face ˆ felul urm˘tor: ın a atributeopt modificatori-de-indexatoropt declarator-de-indexator {declaratiide-accesor} Modificatorii de indexator pot fi: new. } set . abstract. Declaratiile de accesor vor a ¸ contine accesor get sau accesor set.

for( int i=2. } } } CURS 4. } for( int i=0. class DataValue { public DataValue(string name. v[1] = 1. Exemplul 2: supraˆ arcarea indexatorilor: ınc˘ using System. i++) { v[i] = v[i-1] + v[i-2].WriteLine(‘‘v[‘‘ + i. i++) { Console. v[0] = 0. } public string Name { get { return(name). CLASE class Test { static void Main() { MyVector v = new MyVector( 10 ).Length.88 { v[index] = value. } } } 2.name = name. object data) { this.data = data. i<v. this.ToString() + ‘‘]=’’ + v[i]).Collections.Length. i<v. using System. } .

4.7. INDEXATORI set { name = value; } } public object Data { get { return(data); } set { data = value; } } string name; object data; } class DataRow { ArrayList row; public DataRow() { row = new ArrayList(); } public void Load() { row.Add(new DataValue("Id", 5551212)); row.Add(new DataValue("Name", "Fred")); row.Add(new DataValue("Salary", 2355.23m)); } public object this[int column] { get { return(row[column - 1]);

89

90 } set { row[column - 1] = value; } }

CURS 4. CLASE

int FindColumn(string name) { for (int index = 0; index < row.Count; index++) { DataValue dataValue = (DataValue) row[index]; if (dataValue.Name == name) return(index); } return(-1); } public object this[string name] { get { return this[FindColumn(name)]; } set { this[FindColumn(name)] = value; } } } class Test { public static void Main() { DataRow row = new DataRow(); row.Load(); DataValue val = (DataValue) row[0]; Console.WriteLine("Column 0: {0}", val.Data); val.Data = 12; // set the ID DataValue val = (DataValue) row["Id"];

4.7. INDEXATORI

91

Console.WriteLine("Id: {0}", val.Data); Console.WriteLine("Salary: {0}", ((DataValue) row["Salary"]).Data); ((DataValue)row["Name"]).Data = "Barney"; // set the name Console.WriteLine("Name: {0}", ((DataValue) row["Name"]).Data); } } 3. Exemplul 3: Indexator cu mai multi parametri: ¸ using System; namespace MyMatrix { class Matrix { double[,] matrix; public Matrix( int rows, int cols ) { matrix = new double[ rows, cols]; } public double this[int i, int j] { get { return matrix[i,j]; } set { matrix[i,j] = value; } } public int RowsNo { get { return matrix.GetLength(0); } }

92

CURS 4. CLASE

public int ColsNo { get { return matrix.GetLength(1); } } static void Main(string[] args) { MyMatrix m = new MyMatrix(2, 3); Console.WriteLine("Lines: {0}", m.RowsNo); Console.WriteLine("Columns: {0}", m.ColsNo); for(int i=0; i<m.RowsNo; i++) { for( int j=0; j<m.ColsNo; j++) { m[i,j] = i + j; } } for(int i=0; i<c.RowsNo; i++) { for( int j=0; j<c.ColsNo; j++) { Console.Write(c[i,j] + " "); } Console.WriteLine(); } } } }

4.8

Operatori

Un operator este un membru care define¸te semnificatia unei expresii ops ¸ erator care poate fi aplicat˘ unei instante a unei clase. Corespunde supraˆ arc˘rii a ¸ ınc˘ a operatorilor din C++. O declaratie de operator are forma: ¸ atributeopt modificatori-de-operator declaratie-de-operator corp-operator Se pot declara operatori unari, binari ¸i de conversie. s

4.8. OPERATORI Urm˘toarele reguli trebuie s˘ fie respectate pentru orice operator: a a 1. Orice operator trebuie s˘ fie declarat public ¸i static. a s

93

2. Parametrii unui operator trebuie s˘ fie de tip valoare; nu se admite s˘ a a fie de tip ref sau out. 3. Acela¸i modificator nu poate ap˘rea de mai multe ori ˆ antetul unui s a ın operator

4.8.1

Operatori unari

Supraˆ arcarea operatorilor unari are forma: ınc˘ tip operator operator-unar-supraincarcabil (tip identificator) corp Operatorii unari supraˆ arcabili sunt: + - ! ˜ ++ – true false. Urm˘toarele ınc˘ a reguli trebuie s˘ fie respectate la supraˆ arcarea unui operator unar (T a ınc˘ reprezint˘ clasa care contine definitia operatorului): a ¸ ¸ 1. Un operator +, -, !, ˜ trebuie s˘ preia un singur parametru de tip T ¸i a s poate returna orice tip. 2. Un operator ++ sau – trebuie s˘ preia un singur parametru de tip T a ¸i trebuie s˘ returneze un rezultat de tip T. s a 3. Un operator unar true sau false trebuie s˘ preia un singur parametru a de tip T ¸i s˘ returneze bool. s a Operatorii true ¸i false trebuie s˘ fie ori ambii definiti, ori nici unul (altfel s a ¸ apare o eroare de compilare). Ei sunt necesari pentru cazuri de genul: if( a==true ) sau if( a==false ) Mai general, ei pot fi folositi ca expresii de control ˆ if, do, while ¸i for, ¸ ın s precum ¸i ˆ operatorul ternar ”? :”. De¸i pare paradoxal, nu este obligatoriu s ın s ca if (a==true) s˘ fie echivalent˘ cu if (!(a==false)), de exemplu pentru a a tipuri SQL care pot fi null, ceea ce nu ˆ ınseam˘ nici true, nici false, ci lips˘ a a de informatie. ¸ Exemplu:

} // read-only property public int this[int index] { . CLASE Exemplul de mai jos arat˘ modul ˆ care se face supraˆ arcarea operaa ın ınc˘ torului ++. // iv2 contains 4x0. ++i) temp[i] = iv[i] + 1.. iv2 = iv1++. // vector of 4x0 IntVector iv2.Length. for (int i = 0.value > 0.. i < iv....Length). } public static bool operator false(DBBool x) { return x. public static bool operator true(DBBool x) { return x... } . return temp.. // iv2 contains 4x2. } } class Test { static void Main() { IntVector iv1 = new IntVector(4). iv1 contains 4x2 } } .value <= 0. iv1 contains 4x1 iv2 = ++iv1.94 public struct DBBool { private int x. } public static IntVector operator++(IntVector iv) { IntVector temp = new IntVector(iv. } // read-write indexer public IntVector(int vectorLength) { . } CURS 4. care poate fi folosit atˆt ca operator de preincrementare cˆt ¸i a a s ca operator de postincrementare: public class IntVector { public int Length { .

8.8. este indicat˘ ¸i definirea metodei Equals(). ınc˘ Cel putin unul dintre cei doi parametri preluati trebuie s˘ fie de tipul contin˘tor. iar al doilea parametru de tip int. Unii operatori trebuie s˘ se a a declare ˆ pereche: ın 1.8.3 Operatori de conversie O declaratie de operator de conversie trebuie introduce o conversie definit˘ ¸ a de utilizator. ∗. operatorii >= ¸i <= s Pentru operaratorul ==. operatorii > ¸i < s 3. 4. ∗ =. indicat de tipul de retur. dar pentru ca ınc˘ ace¸tia s˘ functioneze. OPERATORI 95 4. /. deoarece as tipul respectiv va putea fi astfel folosit ¸i de c˘tre limbaje care nu suport˘ s a a supraˆ arcarea operatorilor. care se va ad˘uga (dar nu va suprascrie) la conversiile predefia nite.2 Operatori binari Declararea unui operator binar se face astfel: tip operator operator-binar-supraincarcabil ( tip identificator. s ¸a . dar pot apela metoda polimorfic˘ Equals() definit˘ ınc˘ a a ˆ clasa object.4. operatorii == ¸i != s 2. conversiile pot fi implicite sau explicite. Un astfel a de operator va face conversia de la un tip surs˘. Declararea unui operator de conversie se face astfel: implicit operator tip (tip parametru) corp explicit operator tip (tip parametru) corp Dup˘ cum se poate deduce. − =. ın Nu se pot supaˆ arca operatorii + =. a ın 3. S ¸i T sunt tipuri diferite s 2. Unul din cele dou˘ tipuri este clasa ˆ care se face definirea. T ¸i S nu sunt object sau tip interfat˘. / =. −. O clas˘ poate s˘ ¸ a a declare un operator de conversie de la un tip surs˘ S la un tip destinatie T a ¸ cu urm˘toarele conditii: a ¸ 1.* / % & | ^ << >> == != > < >= <=. ¸ ¸ a ¸ a Operatorii de shiftare trebuie s˘ aib˘ primul parametru de tipul clasei ˆ care a a ın se declar˘. tip identificator) corp Operatorii binari supraˆ arcabili sunt: + . este suficient s˘ se supraˆ s a ¸ a ıncarce operatorii corespunz˘tori: a +. indicat de tipul parametrua lui din antet la un tip destinatie.

} } Prima conversie este implicit˘ pentru c˘ nu va duce la pierderea de informatie. a s a 4. } public static implicit operator byte(Digit d) { return d. } public static explicit operator Digit(byte b) { return new Digit(b).8.96 4.4 Exemplu: clasa Fraction using System. int)"). T ¸i S nu sunt baze una pentru cealalt˘. public class Fraction { public Fraction(int numerator.WriteLine("In constructor Fraction(int. this. public Digit(byte value) { if (value < 0 || value > 9) throw new ArgumentException(). a Exemplu: using System. CLASE Un bun design asupra operatorilor de conversie are ˆ vedere urm˘toarele: ın a • Conversiile implicite nu ar trebui s˘ duc˘ la pierdere de informatie sau a a ¸ la aparitia de exceptii. s a CURS 4. public class Digit { byte value. .value. atunci neap˘rat trebuie declarat˘ a a a ca o conversie explicit˘.value = value. a a ¸ Cea de doua poate s˘ arunce o exceptie (via constructor) ¸i de aceea este a ¸ s declarat˘ ca ¸i conversie explicit˘. int denominator) { Console. ¸ ¸ • Dac˘ prima conditie nu este ˆ a ¸ ındeplinit˘.

numerator=numerator.WriteLine("In Constructor Fraction(int)"). numerator = wholeNumber. return new Fraction(theInt). Fraction rhs) { Console.WriteLine("In operator =="). } public static bool operator !=(Fraction lhs.numerator / theFraction.numerator == rhs. if (! (o is Fraction) ) { .numerator ) { return true. return theFraction. return !(lhs==rhs). if (lhs. this. OPERATORI this.WriteLine("In operator !=").WriteLine("In conversie implicita la Fraction"). Fraction rhs) { Console.Console.4.WriteLine("In conversie explicita la int"). } public Fraction(int wholeNumber) { Console.denominator=denominator. } 97 public static implicit operator Fraction(int theInt) { System.denominator * lhs. } public override bool Equals(object o) { Console.Console.8. denominator = 1.WriteLine("In metoda Equals").denominator * rhs.denominator. } return false. } public static explicit operator int(Fraction theFraction) { System. } public static bool operator==(Fraction lhs.

numerator * lhs. if (f5 == f2) { Console. f3. Fraction f4 = f3 + 5.denominator * rhs. return s.ToString( ) + "/" + denominator.ToString( )). lhs. } private int numerator. Console.ToString( )). } public class Tester { static void Main( ) { Fraction f1 = new Fraction(3.WriteLine("f1 + f2 = f3: {0}".denominator ).ToString( )). int secondProduct = rhs. Console. Console. Fraction f3 = f1 + f2.WriteLine("f2: {0}".4).denominator. // 1/2 + 3/4 == (1*4) + (3*2) / (2*4) == 10/8 int firstProduct = lhs. private int denominator. } return this == (Fraction) o.4). Console.ToString( )).WriteLine("In operator+"). f4. f2. CURS 4. CLASE } public static Fraction operator+(Fraction lhs. f1. Fraction f5 = new Fraction(2. Fraction rhs) { Console.4).WriteLine("f3 + 5 = f4: {0}".ToString( ).98 return false.WriteLine("F5: {0} == F2: {1}".numerator * rhs. .denominator. Fraction f2 = new Fraction(2. //ar mai trebui facuta reducerea termenilor } public override string ToString( ) { String s = numerator.WriteLine("f1: {0}". return new Fraction( firstProduct + secondProduct.

Cˆnd exist˘ cˆmpuri instant˘ care au o expresie de initializare ¸ r a a a ¸a ¸ ˆ afara constructorilor clasei respective. Declararea unui ¸ ¸a astfel de constructor se face ˆ felul urm˘tor: ın a atributeopt modificatori-de-constructor declarator-de-constructor corp-constructor Un modificator de constructor poate fi: public. atunci compilatorul va ¸ ¸ ¸a crea automat unul implicit.9. s ¸ a ¸ ¸ 4. O clas˘ care este mo¸tenit˘ dintr-o alt˘ clas˘ ce a s a a a nu are constructori f˘r˘ parametri va trebui s˘ utilizeze un apel de constructor aa a de clas˘ de baz˘ pentru care s˘ furnizeze parametrii potriviti. internal. f2. acest apel se a a a ¸ face prin intermediul initializatorului de constructor. private.4. Un constructor poate ¸ apela la un alt constructor al clasei din care face parte pentru a efectua initializ˘i. s a Un constructor are acela¸i nume ca ¸i clasa din care face parte ¸i nu s s s returneaz˘ un tip. Constructorii de instant˘ nu se mo¸tenesc. Un declarator de constructor are forma: nume-clasa (lista-parametrilor-formaliopt ) initializator-de-constructoropt unde initializatorul-de-constructor are forma: : base( lista-argumenteopt ) sau : this( lista-argumenteopt ). } } } 99 4.ToString( )). Corp-constructor poate fi: un bloc de declaratii ¸i instructiuni delimitat de ¸ s ¸ acolade sau caracterul punct ¸i virgul˘.10 Constructori statici Un constructor static este un membru care implementeaz˘ actiunile cerute a ¸ pentru initializara unei clase. CONSTRUCTORI DE INSTANTA ¸˘ f5. extern. Declararea unui constructor static se face ca ¸ mai jos: .ToString( ).9 Constructori de instant˘ ¸a Un constructor de instant˘ este un membru care implementeaz˘ actiuni ¸a a ¸ care sunt cerute pentru a initializa o instant˘ a unei clase. Pentru a nu se permite a crearea sau mo¸tenirea unei clase trebuie ca aceast˘ clas˘ s˘ contin˘ cel putin s a a a ¸ a ¸ un constructor definit de utilizator ¸i toti constructorii s˘ fie declarati privati. Dac˘ o clas˘ a ¸a s a a nu contine nici o declaratie de constructor de instant˘. atunci aceste initializ˘ri se vor face ın ¸ a ˆ ınainte de apelul de constructor al clasei de baz˘. protected.

Red. 0. this. 255). public static readonly Color Blue. 0). Un constructor static se va executa cel mult o dat˘ ˆ ınc˘ a ıntr-o aplicatie. public static readonly Color Green.red = red. Acest apel este nedeterminist. nu se pot apela direct ¸i nu se pot supras s ˆ arca. a a a Un astfel de constuctor nu are specificator de acces ¸i poate s˘ acceseze doar s a membri statici. necunoscˆndu–se exact cˆnd sau dac˘ se va apela.100 CURS 4. int blue) { this. public static readonly Color Red. int green. // constructor static static Color() { Red = new Color(255. 255. CLASE atributeopt modificator-de-constructor-static identificator( ) corp Modificatorii de constructori statici se pot da sub forma: externopt static sau static externopt Constructorii statici nu se mo¸tenesc.green = green. } int red. this. 0). int green.blue = blue. ¸ Se garanteaz˘ faptul c˘ acest constructor se va apela ˆ a a ınaintea cre˘rii vreunei a instante a clasei respective sau ˆ ¸ ınaintea accesului la un membru static. 0. int blue. . Blue = new Color(0. } } class Test { static void Main() { Color background = Color. Exemplu: class Color { public Color(int red. Green = new Color(0.

Next = next.F’’).B. this. Node next) { this.11. class A { class B { public static void F() { Console.4. .Data = data. } } static void Main() { A. public Node Next.11 Clase interioare O clas˘ contine membri. CLASE INTERIOARE } } 101 4. iar ˆ particular ace¸tia pot fi ¸i clase. public Node(object data. } } Exemplul 2: public class List { // Private data structure private class Node { public object Data. a ¸ ın s s Exemplul 1: using System. private Node last = null.B. } } private Node first = null.F().WriteLine(‘‘A.

internal sau private (implicit private).} public void AddToBack(object o) {.} public object RemoveFromFront() {. O clas˘ declarat˘ ˆ interiorul unei structuri poate fi declarat˘ a a ın a public. public Nested(C c) { this_c = c. internal.G().. n. } public class Nested { C this_c....102 //Interfata publica public void AddToFront(object o) {. class C { int i = 123.} } } CURS 4....} public object RemoveFromBack() {..NumeClasaInterioara (a¸a cum este ar˘tat ˆ Exemplul 1).. protected. de unde se deduce c˘ o s a ın a clas˘ interioar˘ se comport˘ ca un membru static al tipului contin˘tor. } public void G() .. a¸a cum se vede ¸ ¸ a s din Exemplul 1. protected internal. Dac˘ o clas˘ interioar˘ are nevoie s˘ acceseze membri instant˘ ai ¸ a a a a a ¸a clasei contin˘toare. private (implicit este private). nu se poate folosi this ˆ ¸ a ın interiorul unei clase interioare pentru a accesa membri instant˘ din tipul ¸a contin˘tor. public void F() { Nested n = new Nested(this). Altfel spus. va trebui s˘ primeasc˘ prin constructor parametrul this ¸ a a a care s˘ se refer˘ la o astfel de instant˘: a a ¸a using System. Crearea unei instante a unei clase interioare nu trebuie s˘ fie precedat˘ ¸ a a de crearea unei instante a clasei exterioare contin˘toare. O a a a ¸ a clas˘ declarat˘ ˆ interiorul unei alte clase poate avea unul din gradele de a a ın accesibilitate public. O clas˘ interioar˘ nu au vreo relatie special˘ cu membrul a a ¸ a predefinit this al clasei contin˘toare. CLASE Accesarea unei clase interioare se face prin NumeClasaExterioara.} public int Count { get {.

} } 103 Se observ˘ de mai sus c˘ o clas˘ interioar˘ poate manipula toti membrii care a a a a ¸ sunt accesibili ˆ interiorul clasei contin˘toare.F(). class C { private static void F() { Console. } } } class Test { static void Main() { C c = new C().4. c.WriteLine("C. ace¸tia pot fi utilizati f˘r˘ a se folosi numele clasei contin˘toare: s ¸ aa ¸ a using System. } } } class Test { static void Main() { C. indiferent de gradul lor de ın ¸ a accesibilitate. } public class Nested { public static void G() { F().Nested. CLASE INTERIOARE { Console. ˆ cazul ˆ care clasa exterioar˘ (contin˘toare) are membri In ın a ¸ a statici.i).G().F").11.WriteLine(this_c. } } .

CLASE Clasele interioare se folosesc intens ˆ cadrul containerilor pentru care treın buie s˘ se construiasc˘ un enumerator. Clasa interioar˘ va fi ˆ acest caz a a a ın strˆns legat˘ de container ¸i va duce la o implementare u¸or de urm˘rit ¸i de a a s s a s ˆ ıntretinut. ¸ .104 CURS 4.

1 Destructori Managementul memoriei este f˘cut sub platforma . ınc˘ s Un destructor este o scurt˘tur˘ sintactic˘ pentru metoda Finalize(). Un destructor nu are modificator de acces. pag. a ın de c˘tre garbage collector. sau cu metode de tipul Dispose().Curs 5 Destructori. a a a Exemplu: ~MyClass() { // Perform some cleanup operations here. se dore¸te s˘ se fac˘ management manın ¸ s a a ual al dealoc˘rii resurselor (de exemplu al resurselor care ¸in de sistemul de a t operare: fi¸iere. parte component˘ a CLR–ului. Close(). POO ˆ C# ın 5. } Metoda de mai sus este automat translatat˘ ˆ a ın: 105 . Programatorul nu poate s˘ suprascrie a ın a sau s˘ apeleze aceast˘ metod˘. nu este mo¸tenit. acest garbage collector scute¸te programatorul de grija dealoc˘rii In s a memoriei. Pentru o explicatie a a ¸ asupra modului cum actioneaz˘ garbage collector-ul. conexiuni la retea sau la baza de date. Dar ˆ anumite situatii. Un destructor se declar˘ ˆ felul urm˘tor: a ın a atributeopt externopt ~identificator() corp-destructor unde identificator este numele clasei. nu poate fi supraˆ arcat.NET ˆ mod automat. etc. nu poate fi apelat manual.Object. sau al s ¸ altor resurse al c˘ror management nu se face de c˘tre CLR). a se vedea [5]. ferestre. ˆ C# exist˘ a a In a posibilitatea de a lucra cu destructori. s ˆ general. 225 ¸ a ¸i urm. care a a a este definit˘ ˆ clasa System.

a ın s a a astfel ˆ at s˘ nu a¸tepte ca garbage collectorul s˘ apeleze destructorul. DESTRUCTORI. dar acest lucru se face nedeterminist (cu toate c˘ apelarea de destructor a se face ˆ cele din urm˘. atunci a a a garbage collectorul va apela el destructorul la un moment dat.//elimina apel de Finalize() } ~ResourceUser() { hwnd. Proıncˆ a s a gramatorul poate scrie o metoda care s˘ fac˘ acest lucru.106 CURS 5. Dac˘ clientul nu apeleaz˘ explicit Dispose(). } } Problema cu destructorul este c˘ el e chemat doar de c˘tre garbage colleca a tor. Se sugereaz˘ a a a definirea unei metode Dispose() care ar trebui s˘ fie explicit apelat˘ atunci a a ˆ plus. este necesar ca tipurile care ima plemeteaz˘ aceast˘ metod˘ s˘ defineasc˘ de asemenea destructor.IDisposable. .Release().Finalize(). a a a a a Exemplu: public class ResourceUser: IDisposable { public void Dispose() { hwnd. Exist˘ cazuri ˆ care programatorul dore¸te s˘ fac˘ dealocarea manual.//elibereaza o fereastra in Win32 GC.SuppressFinalization(this). a a ˆ acest caz. clasa recˆnd resurse de sistem de operare trebuie s˘ fie eliberate. } finally { base. care contine a a ¸ ¸ aceast˘ metod˘.Release(). POO ˆ C# IN protected override void Finalize() { try { // Perform some cleanup operations here. dac˘ programatorul nu ˆ ın a a ımpiedic˘ explicit acest a lucru). Dispose() ar trebui s˘ inhibe executarea ulterioar˘ de garbage In a a collector pentru instanta curent˘. Aceast˘ manevr˘ permite evitarea eliber˘rii ¸ a a a a unei resurse de dou˘ ori. ˆ Intrucˆt a utilizatorul poate s˘ nu apeleze Dispose(). In a a spectiv˘ ar trebui s˘ implementeze interfata System.

ˆ care din clase de baz˘ ın a (mamifer sau angajat) descind alte clase. } Modalitatea cea mai indicat˘ este folosirea unui bloc using. Toate acestea duc la crearea unei ierarhii de clase. etc. O clas˘ de baz˘ define¸te un tip comun.2. etc. Deseori ˆ ıntre clasele pe care le model˘m putem observa relatii de a ¸ genul “este un/o”: un om este un mamifer.2. ˆ acest In a a s a a a ın caz se va considera c˘ ea este implicit derivat˘ din clasa predefinit˘ object a a a (tot una cu System.5. un salariat este un angajat. ferestre de dialog. care pe lˆng˘ cˆmpuri din clasa de a a a baz˘ mai au ¸i caracteristici proprii. Este indicat ca s˘ se adauge o metod˘ Close() care s˘ fac˘ doar apel de Dispose(): a a a a //in interiorul unei clase public void Close() { Dispose(). Obtinerea unei clase derivate plecˆnd a s ¸ a de la alt˘ clas˘ se nume¸te specializare. SPECIALIZAREA SI GENERALIZAREA ¸ } } 107 Pentru anumite clase C# se pune la dispozitie o metod˘ numit˘ Close() ˆ ¸ a a ın locul uneia Dispose(): fisiere. ˆ C# o clas˘ nu trebuie s˘ mo¸teneasc˘ explicit din alt˘ clas˘. socket-uri. compatibil cu oricare a a s din clasele derivate (direct sau indirect). ¸ ın 5.Object). eliminˆnd s a a astfel complicatiile ˆ alnite ˆ C++.1 Specificarea mo¸tenirii s ˆ C# se pentru o clas˘ D se define¸te clasa de baz˘ B folosind urm˘toarea In a s a a formul˘: a . operatia invers˘ purtˆnd numele de a a s ¸ a a generalizare. C# nu permite mo¸tenire multipl˘. se permite totu¸i im¸ ıntˆ ın a s plementarea de mai multe interfete (la fel ca ˆ Java). Ca alternativ˘.2 Specializarea ¸i generalizarea s Specializarea reprezint˘ o tehnic˘ de a obtine noi clase pornind de la cele a a ¸ existente. caz ˆ care se va a ın elibera obiectul alocat (via metoda Dispose()) la sfˆr¸itul blocului: as using( obiect ) { //cod }//aici se va apela automat metoda Dispose() 5.

Acest apel se face prin initializator de a ¸ constructor care are forma: dou˘ puncte urmate de base(parametrii-efectivi).108 class D: B { //declaratii } CURS 5. string ssn. public Salaried( string name. DESTRUCTORI. this. constructorul clasei derivate trebuie s˘ fac˘ initializ˘rile cˆmpurilor a a ¸ a a ˆ conformitate cu parametrii transmi¸i. chiar dac˘ o parte din aceste cˆmpuri ın s a a provin din clasa de baz˘.name = name. this. a . e nevoie ca ˆ clasa derivat˘ s˘ se fac˘ un apel exs ın a a a plicit al constructorului clasei de baz˘.2 Apelul constructorilor din clasa de baz˘ a ˆ exemplul anterior nu s–a definit nici un constructor ˆ clasa de baz˘ In ın a Employee. Mai logic ar fi ca ˆ clasa de baz˘ s˘ se g˘seasc˘ un a ın a a a a ˆ constructor care s˘ initializeze cˆmpurile proprii: name ¸i ssn. double salary ) { this.salary = salary. a a ın a Exemplu: //clasa de baza in C# public class Employee { protected string name. Intrucˆt cona ¸ a s a structorii nu se mo¸tenesc.ssn = ssn. } //clasa derivata in C# public class Salaried : Employee { protected double salary. } } Se observ˘ c˘ cˆmpurile name ¸i ssn din clasa de baz˘ sunt accesibile ˆ clasa a a a s a ın derivat˘. a a 5.2. datorit˘ specificatorului de acces protected. POO ˆ C# IN Dac˘ pentru o anumit˘ clas˘ nu se specific˘ dou˘ puncte urmate de numele a a a a a unei clase de baz˘ atunci object va deveni baz˘ pentru clasa ˆ cauz˘. protected string ssn.

Dac˘ dup˘ un constructor al unei clase aa a a derivate nu se specific˘ un initializator de constructor. name. public Employee( string name. dac˘ nu exist˘ nici un constructor implicit ˆ clasa de baz˘. double salary): base(name. } } public class Salaried : Employee { protected double salary. ssn). a a ¸ ¸ ın Dac˘ o clas˘ de baz˘ nu are definit nici un constructor. System.Console.ssn = ssn. ˆ ımpreun˘ cu parametrii adecvati. atunci va fi apelat a ¸ constructorul implicit (fie creat automat de compilator.WriteLine(‘‘Salaried constructor: {0}’’. a ¸ . this. ‘‘1234567890’’. } } class Test { Salaried s = new Salaried(‘‘Jesse’’. fie scris de c˘tre a programator). public Salaried(string name. SPECIALIZAREA SI GENERALIZAREA ¸ 109 public class Employee { protected string name. } La rulare se va obtine: ¸ Employee constructor: Jesse.WriteLine(‘‘Employee constructor: {0}. System. 100000.name = name.Console. atunci se va a a a crea unul implicit (f˘r˘ parametri). ssn) { this.00 de unde se deduce c˘ apelul de constructor de clas˘ de baz˘ se face ˆ a a a ınaintea execut˘rii oric˘ror alte instructiuni continute ˆ constructorul clasei derivate. string ssn.salary = salary. a a ın a atunci programatorul trebuie s˘ specifice un constructor din clasa de baz˘ a a care va fi apelat. salary). 1234567890 Salaried constructor: 100000.5. string ssn) { this.2.00). {1}’’. protected string ssn.

110

CURS 5. DESTRUCTORI. POO ˆ C# IN

5.2.3

Operatorii is ¸i as s

Operatorul is Operatorl is este folosit pentru a verifica dac˘ un anumit obiect este de a un anumit tip. Este folosit de obicei ˆ ınainte operattiilor de downcasting ¸ (conversie explicit˘ de la un tip de baz˘ la unul derivat). Operatorul se a a folose¸te astfel: s instanta is NumeClasa rezultatul acestei operatii fiind true sau false. ¸ Exemplu: Employee e = ...; if (e is Salaried) { Salaried s = (Salaried)e; } ˆ cazul ˆ care s–ar face conversia explicit˘ iar obiectul nu este de tipul la In ın a care se face conversia ar rezulta o exceptie: System.InvalidCastException. ¸ Operatorul as Acest operator este folosit pentru conversii explicite, returnˆnd un obiect a de tipul la care se face conversia sau null dac˘ conversia nu se poate face a (nu se arunc˘ exceptii). Determinarea validit˘¸ii conversiei se face testˆnd a ¸ at a valoarea rezultat˘ fat˘ de null: dac˘ rezultatul e null atunci conversia nu s–a a ¸a a putut face. Ca ¸i precedentul operator se folose¸te ˆ special la downcasting. s s ın Exemplu: Employee e = ...; Salaried s = e as Salaried; if (s != null) { //se lucreaza cu instanta valida de tip Salaried }

5.3

Clase sealed

Specificatorul sealed care se poate folosi ˆ ınaintea cuvˆntului cheie class a specific˘ faptul c˘ clasa curent˘ nu se poate deriva. Este o eroare de compilare a a a ca o clas˘ sealed s˘ fie declarat˘ drept clas˘ de baz˘. a a a a a

5.4. POLIMORFISMUL

111

5.4

Polimorfismul

Polimorfismul este capacitatea unei entit˘¸i de a lua mai multe forme. at ˆ limbajul C# polimorfismul este de 3 feluri: parametric, ad–hoc ¸i de In s mo¸tenire. s

5.4.1

Polimorfismul parametric

Este cea mai slab˘ form˘ de polimorfism, fiind reg˘sit˘ ˆ majoritatea a a a a ın altor limbaje, ce nu sunt orientate pe obiecte: Pascal, C. Prin polimorfismul parametric se permite ca o implementare de functie s˘ poat˘ prelucra ¸ a a orice num˘r de parametri. Acest lucru se poate obtine prin folosirea unui a ¸ parametru de tip params (vezi 3.2).

5.4.2

Polimorfismul ad–hoc

Se mai nume¸te ¸i supraˆ arcarea metodelor, mecanism prin care ˆ s s ınc˘ ın cadrul unei clase se pot scrie mai multe metode, avˆnd acela¸i nume, dar a s tipuri ¸i numere diferite de parametri de apel. Alegerea functiei care va fi s ¸ apelat˘ se va face la compilare, pe baza corespondentei ˆ a ¸ ıntre tipurile de apel ¸i cele formale. s

5.4.3

Polimorfismul de mo¸tenire s

Este forma cea mai evoluat˘ de polimorfism. Dac˘ precedentele forme de a a polimorfism sunt aplicabile f˘r˘ a se pune problema de mo¸tenire, ˆ acest aa s ın caz este necesar s˘ existe o ierarhie de clase. Mecanismul se bazeaz˘ pe faptul a a c˘ o clas˘ de baz˘ define¸te un tip care este compatibil din punct de vedere a a a s al atribuirii cu orice tip derivat, ca mai jos: class B{...} class D: B{...} class Test { static void Main() { B b = new D();//upcasting=conversie implicita catre baza } } ˆ Intr–un astfel de caz se pune problema: ce se ˆ ampl˘ cu metodele avˆnd ıntˆ a a aceea¸i list˘ de parametri formali ¸i care se reg˘sesc ˆ cele dou˘ clase? s a s a ın a

112

CURS 5. DESTRUCTORI. POO ˆ C# IN

S˘ consider˘m exemplul urm˘tor: avem o clas˘ Shape care contine o a a a a ¸ metod˘ public void Draw(); din Shape se deriveaz˘ clasa Polygon care implea a menteaz˘ aceea¸i metod˘ ˆ mod specific. Problema care se pune este cum a s a ın se rezolv˘ un apel al metodei Draw ˆ context de upcasting: a ın class Shape { public void Draw() { System.Console.WriteLine(‘‘Shape.Draw()’’); } } class Polygon: Shape { public void Draw() { System.Console.WriteLine(‘‘Polygon.Draw()’’); //desenarea s-ar face prin GDI+ } } class Test { static void Main() { Polygon p = new Polygon(); Shape s = p;//upcasting s.Draw(); p.Draw(); } } La compilarea acestui cod se va obtine un avertisment: ¸ warning CS0108: The keyword new is required on Polygon.Draw() because it hides inherited member Shape.Draw() dar despre specificatorul new vom vorbi mai jos (oricum, ad˘ugarea lui nu a va schimba cu nimic comportamentul de mai jos, doar va duce la disparitia ¸ de avertisment). Codul de mai sus va afi¸a: s Shape.Draw() Polygon.Draw()

5.4. POLIMORFISMUL

113

Dac˘ cea de–a doua linie afi¸at˘ este conform˘ cu intuitia, primul rezultat a s a a ¸ este discutabil, dar justificabil: apelul de metod˘ Draw() este rezolvat ˆ a ın fiecare caz la compilare pe baza tipului declarat al obiectelor; ca atare apelul precedent este legat de corpul metodei Draw din clasa Shape, chiar dac˘ s a a fost instantiat de fapt pe baza unui obiect de tip Polygon. ¸ Este posibil ca s˘ se doreasc˘ schimbarea acestui comportament: apelul de a a metod˘ Draw s˘ fie rezolvat ˆ functie de tipul efectiv al obiectului care face a a ın ¸ acest apel, ¸i nu de tipul formal declarat. ˆ cazul precedent, apelul s.Draw() s In trebuie s˘ se rezolve de fapt ca fiind c˘tre metoda Draw() din Polygon, pentru a a c˘ acesta este tipul la rulare al obiectului s. Cu alte cuvinte, apelul ar trebui a s˘ fie rezolvat la rulare ¸i nu la compilare, ˆ functie de natura obiectelor. a s ın ¸ Acest comportament polimorfic este referit sub denumirea polimorfism de mo¸tenire. s

5.4.4

Virtual ¸i override s

Pentru a asigura faptul c˘ legarea apelului de metode se face la rulare a ¸i nu la compilare, e necesar ca ˆ clasa de baz˘ s˘ se specifice c˘ metoda s ın a a a Draw() este virtual˘, iar ˆ clasa derivat˘ pentru aceea¸i metod˘ trebuie s˘ a ın a s a a se spun˘ c˘ este o suprascriere a celei din baz˘: a a a class Shape{ public virtual void Draw(){...} } class Polygon{ public override void Draw(){...} } ˆ urma execut˘rii metodei Main din clasa de mai sus, se va afi¸a: In a s Polygon.Draw() Polygon.Draw() adic˘ s–a apelat metoda corespunz˘toare tipului efectiv de la rulare, ˆ fiecare a a ın caz. ˆ cazul ˆ care clasa Polygon este la rˆndul ei mo¸tenit˘ ¸i se dore¸te In ın a s a s s ca polimorfismul s˘ functioneze ˆ continuare va trebui ca ˆ aceast˘ a treia a ¸ ın ın a clas˘ s˘ suprascrie (override) metoda Draw(). a a Un astfel de comportament polimorfic este benefic atunci cˆnd se folose¸te a s o colectie de obiecte de tipul unei clase de baz˘: ¸ a Shape[] painting = new Shape[10]; painting[0] = new Shape();

114

CURS 5. DESTRUCTORI. POO ˆ C# IN

painting[1] = new Polygon(); ... foreach( Shape s in painting) s.Draw();

5.4.5

Modificatorul new pentru metode

Modificatorul new se folo¸este pentru a indica faptul c˘ o metod˘ dintr-o s a a clas˘ derivat˘ care are aceea¸i semn˘tur˘ cu una dintr–o clas˘ de baz˘ nu a a s a a a a este o suprascriere a ei, ci o nou˘ metod˘. Este ca ¸i cum metoda declarat˘ a a s a new ar avea o semn˘tur˘ diferit˘. a a a S˘ presupunem urm˘torul scenariu: compania A creaz˘ o clas˘ A care a a a a are forma: public class A{ public void M(){ Console.WriteLine(‘‘A.M()’’); } } O alt˘ companie B va crea o clas˘ B care mo¸tene¸te clasa A. Compania a a s s B nu are nici o influent˘ asupra companiei A (sau asupra modului ˆ care ¸a ın aceasta va face modific˘ri asupra clasei A). Ea va defini ˆ interiorul clasei B a ın o metod˘ M() ¸i una N(): a s class B: A{ public void M(){ Console.WriteLine(‘‘B.M()’’); N(); base.M(); } protected virtual void N(){ Console.WriteLine(‘‘B.N()’’); } } Atunci cˆnd compania B compileaz˘ codul, compilatorul C# va produce a a urm˘torul avertisment: a warning CS0108: The keyword new is required on ‘B.M()’ because it hides inherited member ‘A.M()’

} protected virtual void N() { Console.N()’.M(). add the override keyword.5. Programatorii din B vor trebui s˘ pun˘ a a ˆ orice caz specificatorul new ˆ ın ınaintea metodei B. Este de dorit ˆ astfel de cazuri compilatorul s˘ avertizeze ın a despre posibile nepotriviri semantice.4. To make the current member override that implementation. a¸a cum a fost creat initial ınt s ¸ de compania A. care va ascunde metoda M() din clasa de baz˘ A. Otherwise. } } La o recompilare f˘cut˘ de B. } } La rulare se va afi¸a: s B.WriteLine(‘‘A. a a a ın metod˘ ce va fi apelat˘ din M(): a a public class A { public void M() { Console. este dat urm˘torul avertisment: a a a warning CS0114: ‘B.M()’’).M() S˘ presupunem c˘ A decide ad˘ugarea unei metode virtuale N() ˆ clasa sa. S˘ presupunem c˘ o aplicatie folose¸te clasa B() ˆ felul urm˘tor: a a ¸ s ın a class App{ static void Main(){ B b = new B().M() B.N() A. POLIMORFISMUL 115 Acest avertisment va notifica programatorul c˘ clasa B define¸te o metod˘ a s a M(). b.N()’ hides inherited member ‘A. N().M(). .WriteLine(‘‘A. add the new keyword.N()’’). Aceast˘ nou˘ metod˘ a a a a ar putea schimba ˆ ¸elesul (semantica) lui M().

Dac˘ B decide c˘ metodele N() nu sunt a a a a a semantic legate ˆ cele dou˘ clase. ˆ acest caz.M() A. care nu suprascrie polimorfic a a metoda din clasa de baz˘.N() suprascrie o metod˘ virtual˘. atunci va specifica new. din cauza polimorfismului). } public virtual void G() { Console.M.WriteLine(‘‘A.WriteLine(‘‘A. ea poate ¸terge definitia metodei B. } } . POO ˆ C# IN ˆ acest mod compilatorul avertizeaz˘ c˘ ambele clase ofer˘ o metod˘ N() In a a a a a c˘ror semantic˘ poate s˘ difere. ultima linie ar fi fost a s a B.6 Metode sealed O metod˘ de tip override poate fi declarat˘ ca fiind de tip sealed. class A { public virtual void F() { Console.N() ultima linie fiind explicat˘ de faptul c˘ B.N() A.M() B.Main va produce: A.N() Ultima linie afi¸at˘ se explic˘ tocmai prin faptul c˘ metoda N() din B este s a a a declarat˘ new ¸i nu override (dac˘ ar fi fost override. Se poate ca B s˘ decid˘ c˘ metodele M() ¸i N() din cele dou˘ clase sunt a a a s a legate semantic. se va afi¸a la ie¸ire: a s s B. ˆ acest caz. a a a a 5. iar In s ¸ pentru a semnala faptul c˘ metoda B.116 CURS 5.4. va ˆ a ınlocui cuvˆntul new cu override.N().F()’’). DESTRUCTORI. a Atunci cˆnd codul din clasa App este rulat. astfel a a ˆ ımpiedicˆndu–se suprascrierea ei ˆ a ıntr–o clas˘ derivat˘ din cea curent˘: a a a using System.G()’’). informˆnd compiın a a latorul de faptul c˘ versiunea sa este una nou˘. metoda a In App.N() suprascrie metoda omonim˘ din a a clasa p˘rinte.M() B.

override. x[3] = new D(). Fiecare a s a a a ¸ clas˘ are o metod˘ void f() care determin˘ afi¸area clasei ˆ care este definit˘ a a a s ın a ¸i pentru care se vor specifica new. } } class C: B { override public void G() { Console. } override public void G() { Console. x[2] = new C(). x[1] = new B().F va ˆ ımpiedica tipul C s˘ suprascrie metoda a F. virtual. sealed. reprezentat˘ ˆ Fig.WriteLine(‘‘B. override. 5.G()’’). } } 117 Modificatorul sealed pentru B.4. sealed S˘ presupunem urm˘toare ierarhie de clase. . x[0] = new A().7 Exemplu folosind virtual. o a a a ın clas˘ X mo¸teneste o clas˘ Y dac˘ sensul s˘getii este de la X la Y.4. POLIMORFISMUL class B: A { sealed override public void F() { Console. new.WriteLine(‘‘C.5. 5.G()’’).F()’’).1.WriteLine(‘‘B. B b = new B(). S˘ presupunem s a c˘ clasa de test arat˘ astfel: a a public class Test { static void Main() { A[] x = new A[4]. A a = new A().

D d = new D(). d. /* secventa 1 */ for(int i=0.f().118 CURS 5. } /* secventa 2 */ a.f(). i<4.f().1: Ierarhie de clase C c = new C(). c. i++) { x[i].f(). DESTRUCTORI. } } ˆ functie de specificatorii metodelor f() din fiecare clas˘.1: . POO ˆ C# IN A +foo(): void D B +foo(): void +foo(): void C +foo(): void Figura 5.f(). se obtin ie¸irile din In ¸ a ¸ s tabelul 5. b.

¸ a ¸ ¸ Analog.5 Clase ¸i metode abstracte s Deseori pentru o anumit˘ clas˘ nu are sens crearea de instante.f D.f() override D.f D.f B. In clasele Employee ¸i Shape ar putea fi gˆndite ca fiind abstracte: ele contin s a ¸ prea putin˘ informatie pentru a putea crea instante utile.f new A.f() a Specificator Ie¸ire secv. ˆ exemplele de mai sus.f C.f new A.f() override C. iar pentru a ˆ a ımpiedica efectiv crearea de instante de acest tip. 1 s Ie¸ire secv. CLASE SI METODE ABSTRACTE ¸ Tabelul 5.f B. 1 s Ie¸ire secv. 2 s Avertisment la compilare deoarece B. 1 s Ie¸ire secv.f a A.f A.f override D. 2 s Specificator Eroare de compilare deoarece C.5. din cauza a a ¸ unei generalit˘¸i prea mari a tipului respectiv.f ˆ ınlocuie¸te A.f D. pentru clasa Shape de mai sus.f A. 2 s Specificator Ie¸ire secv.f override B.f override override A.f B. De exemplu.f() virtual A.f nu poate suprascrie metoda nevirtual˘ B. pentru o anumit˘ metod˘ din interiorul unei clase uneori nu se a a poate specifica o implementare.f new A. 1 s Ie¸ire secv.f new B.f C.5. ¸ 119 Metoda Specificator Ie¸ire secv.f A.f virtual A.f B.f D. .f virtual sealed override override override 5.f C.f virtual A.1: Efecte ale diferitilor specificatori.f virtual B.f() override B.f override D.f A.f override virtual virtual A.f nu poate fi suprascris˘ de C.f new C.f C. 2 s Specificator Ie¸ire secv.f A. se ¸ va specifica cuvˆntul abstract ˆ a ınaintea metodei.f D.f s Specificator Eroare de compilare deoarece deoarece B. Spunem c˘ aceast˘ clas˘ este at a a a abstract˘.

¸ ori static. tocmai din cauza a generalit˘¸ii acestei clase. protected. virtual. Nu se poate specifica pentru o metod˘ din interiorul a unei interfete: abstract. public.120 CURS 5. O ¸a interfat˘ poate s˘ mo¸teneasc˘ de la zero sau mai multe interfete. internal. override. internal. O clas˘ sau o structur˘ care imple¸a s a a menteaz˘ o interfat˘ ader˘ la acest contract. private. private. fie s˘ se declare ca fiind a a s a aa a abstract˘. POO ˆ C# IN este imposibil s˘ se dea o implementare la metoda Draw(). ¸ O interfat˘ poate contine metode. protected. a a a a Exemplu: abstract class Shape { public abstract void Draw(). orice metod˘ abstract˘ este automat ¸i virtual˘. Corpul ¸a a s a ¸ interfetei contine declaratii de metode. Pentru a se asigura tratarea polimorfic˘ a acestui a tip abstract. Declararea ıns˘ ¸ a ¸ unei interfete se face astfel: ¸ atributeopt modificatori-de-interfat˘opt interface identificator baza-interfeteiopt ¸a ¸ corp-interfat˘ . 5. . indexatori. Ea ¸a ¸ at ˆ a nu va contine implement˘ri pentru acestea.6 Interfete ¸ O interfat˘ define¸te un contract. Ar fi util dac˘ pentru aceast˘ metod˘ programat a a a atorul ar fi obligat s˘ dea implement˘ri specifice ale acestei metode pentru a a diversele clase derivate. propriet˘¸i. Existenta de metode neimplementate nu va permite instantierea a ¸ ¸ clasei respective. evenimente. public.opt ¸a Modificatorii de interfat˘ sunt: new. Exemplu: interface IStorable { void Read( ). DESTRUCTORI. doar declaratii. Relatia dintre o interfat˘ ¸i a ¸a a ¸ ¸a s un tip care o implementeaz˘ este deosebit˘ de cea existent˘ ˆ a a a ıntre clase (este un/o): este o relatie de implementare. f˘r˘ implement˘ri. //de remarcat lipsa implementarii si semnul punct si virgula } Orice clas˘ care este derivat˘ dintr–o clas˘ abstract˘ va trebui fie s˘ nu aib˘ a a a a a a nici o metod˘ abstract˘ mo¸tenit˘ f˘r˘ implementare. Orice metod˘ a a s a a care este declarat˘ abstract˘ implic˘ declararea clasei ca fiind abstract˘. Orice metod˘ are ¸ ¸ ¸ aa a a gradul de acces public.

Metoda din clas˘ trebuie s˘ fie declarat˘ public˘ ¸i nestatic˘. } public void Write() { Console. Tipul de retur al metodei din clas˘ trebuie s˘ coincid˘ cu tipul de retur a a a al metodei din interfat˘ ¸a 2.5. interface ISavable { void Read().Read()").6.WriteLine("TextFile. Tipul parametrilor formali din metod˘ trebuie s˘ fie acela¸i cu tipul a a s parametrilor formali din interfat˘ ¸a 3. } O clas˘ care implementeaz˘ o astfel de interfat˘ se declar˘ ca mai jos: a a ¸a a class Document: IStorable { public void Read(){/*cod*/} public void Write(){/*cod*/} //alte declaratii } 121 O clas˘ care implementeaz˘ o interfat˘ trebuie s˘ defineasc˘ toate metodele a a ¸a a a care se reg˘sesc ˆ interfata respectiv˘.WriteLine("TextFile. Urm˘toarele reguli trebuie respectate a ın ¸ a a la implementarea de interfete: ¸ 1. a a a as a Aceste implement˘ri pot fi declarate folosind specificatorul virtual (deci suba clasele clasei curente pot folosi new ¸i override).Write()"). . void Write(). } public class TextFile : ISavable { public virtual void Read() { Console. s Exemplu: using System. INTERFETE ¸ void Write().

zipRef. textRef. DESTRUCTORI.Read() .WriteLine("ZipFile. TextFile textRef = new ZipFile(). } public new void Write() { Console.WriteLine("\nISavable reference to ZipFile").Write(). Console. ISavable savableRef = textRef as ISavable. if(zipRef!= null) { zipRef.WriteLine("\nTextFile reference to ZipFile").Read().Read()").WriteLine("\nZipFile reference to ZipFile"). savableRef.Write(). textRef. POO ˆ C# IN } public class ZipFile : TextFile { public override void Read() { Console.Write()").WriteLine("ZipFile. if(savableRef != null) { savableRef.Read(). ZipFile zipRef = textRef as ZipFile. } } public class Test { static void Main() { Console.Write().122 } CURS 5. } } } La ie¸ire se va afi¸a: s s TextFile reference to ZipFile ZipFile. } Console.Read().

Read() ZipFile.Write() ISavable reference to ZipFile ZipFile. a ¸a Exemplu: . pe baza obiectelor create. a Metodele din interfete care s–au implementat explicit (prin calificarea lor ¸ cu numele interfetei de origine) nu pot fi declarate abstract. ın S˘ presupunem c˘ exista o interfat˘ I avˆnd metoda M() care este ima a ¸a a plementat˘ de o clas˘ C. override. dac˘ se dore¸te doar r˘spunsul la ˆ In a s a ıntrebarea ”este obiectul curent un implementator al interfetei I ?”. is. asemenea metode nu pot fi accesate direct prin intermediul unui obiect (obiect. Mai mult.5. Aceast˘ tehnic˘ permite ascunderea metodelor s a a mo¸tenite dintr-o interfat˘. ¸ new. atunci a s a a as ¸a este mai eficient˘ folosirea lui as. Dac˘ se ¸tie c˘ va trebui f˘cut˘ ¸i o conversie la tipul interfat˘.Write() ZipFile reference to ZipFile ZipFile.Read(). In ¸ a care sunt implementate din interfat˘ s˘ se fac˘ via o referint˘ la interfata ¸a a a ¸a ¸ respectiv˘. virtual. ca atare a nu e util ca a a a ¸ ın metoda M() s˘ fie declarat˘ public˘.NumeMetoda). deoarece prin implementare explicit˘ a metodelor a ¸a a a aceste devin private ¸i singura modalitate de acces a lor este upcasting-ul s c˘tre interfat˘. se prefer˘ ca apelul metodelor interfete. care define¸te metoda M().//etc } ˆ general.6. INTERFETE ¸ TextFile. atunci se recomand˘ folosirea operatorului ¸ a is. obtinut˘ prin intermediul operatorului as (ca mai sus) sau dup˘ a ¸ a a o testare prealabil˘ prin is urmat˘ de conversie explicit˘. acestea devenind private (calificarea lor ca fiind s ¸a publice este semnalat˘ ca o eroare). Este posibil ca aceast˘ a a s a metod˘ s˘ nui aib˘ o semnificatie ˆ afara clasei C.Write() 123 ˆ exemplul de mai sus se folo¸este operatorul as pentru a obtine o referint˘ la In s ¸ ¸a ˆ general. Afirmatia se bazeaz˘ pe studiul codului IL a ¸ a rezultat ˆ fiecare caz. ci doar prin intermediul unei conversii c˘tre interfat˘ respectiv˘. ca mai jos: a a a if (textRef is ISavable) { ISavable is = (ISavable)textRef.Read() TextFile. Mecanismul care permite acest lucru se a a a nume¸te ascunderea numelor.

} } class NameHidingApp { public static void Main() { Console.Bind() { Console.. POO ˆ C# IN public class EditBox : IDataBound { // implementare de IDataBound void IDataBound..")."). Console.WriteLine("Binding to data store.WriteLine(). Atunci cˆnd a ¸ a dou˘ interfete au o metod˘ cu aceea¸i semn˘tur˘. public interface IDataBound { void Bind().Bind(). } } Este posibil ca un tip s˘ implementeze mai multe interfete. . Cel mai simplu..124 using System. el poate s˘ furnizeze o singur˘ a a implementare pentru ambele metode."). // Functioneaza deoarece s-a facut conversie la IDataBound bound. } CURS 5. Console.Bind().WriteLine("Apel EditBox.WriteLine().Bind(). programatorul are mai a ¸ a s a a multe variante de lucru.. //EROARE: Aceasta linie nu se compileaza deoarece metoda //Bind nu mai exista ca metoda publica in clasa EditBox edit. EditBox edit = new EditBox(). IDataBound bound = (IDataBound)edit.. Console.. ca mai jos: interface IFriendly { void GreetOwner() .WriteLine("Apel (IDataBound) EditBox. DESTRUCTORI.Bind().

Eat" ) .GreetOwner() { Console. a a a a class Dog : Pet. INTERFETE ¸ } interface IAffectionate { void GreetOwner() . } } class Dog : Pet.6.WriteLine( "Dog. IFriendly { public override void Eat() { Console. } public void GreetOwner() { Console. } void IFriendly. } abstract class Pet { public virtual void Eat() { Console.WriteLine( "Pet. } void IAffectionate. IFriendly { public override void Eat() { Console.WriteLine( "Dog.Eat" ) . IAffectionate.5.Eat" ) .WriteLine( "Jump up!" ) . IAffectionate.WriteLine( "Woof!" ) . } } public class Pets .WriteLine( "Woof!" ) . } } 125 O alt˘ modalitate este s˘ se specifice implicit care metod˘ este implementat˘.GreetOwner() { Console.

WriteLine( "Woof!" ) . DESTRUCTORI. a ¸a Dezavantajul claselor abstracte este c˘ nu poate fi decˆt baz˘ unic˘ pentru a a a a orice alt˘ clas˘. Dac˘ aceste capabilit˘¸i ar fi folosite de c˘tre obiecte care nu sunt a a at a legate ˆ ıntre ele. mansBestFriend. atunci se poate face apel de tipul dog. ın ¸ s Cˆteva principii generale de utilizare a lor sunt date mai jos. atunci ar fi indicat˘ o interfat˘.GreetOwner() . Dar totu¸i ele nu se pot substitui reciproc. a a a a a Un alt aspect este bazat pe obiectele care ar folosi capabilit˘¸ile din tipul at de baz˘. apelurile de metode din interfat˘ r˘mˆn de aseme¸a ¸a a a nea valide. (mansBestFriend as IAffectionate). a a . 5. POO ˆ C# IN static void Main() { IFriendly mansBestFriend = new Dog() . } (care a fost initial definit˘).126 { CURS 5. Rezultatul este ca ¸i la exemplul precedent: se afi¸eaz˘ mesajul s s a Woof.6.GreetOwner() . a Dac˘ o relatie se poate exprima mai degrab˘ ca “este un/o” decˆt altfel. } } La ie¸ire se va afi¸a: s s Jump up! Woof! Dac˘ ˆ a ˆ clasa Dog se adaug˘ metoda a ıns˘ ın a public void GreetOwner() { Console.GreetOwner() ¸ a (dog este instant˘ de Dog). a ¸ a a atunci entitatea de baz˘ ar trebui gˆndit˘ ca o clas˘ abstract˘.1 Clase abstracte sau interfete? ¸ Atˆt interfetele cˆt ¸i clasele abstracte au comportamente similare ¸i pot a ¸ a s s fi folosite ˆ situatii similare.

terminarea copierii unor fi¸iere. etc. pentru care clasa interesat˘ de evenimentul de ap˘sare va da o a a implementare. ˆ s a Intr–un limbaj precum C++. dar ˆ a s a ıntr–o manier˘ orientat˘ obiect ¸i cu garantii a a s ¸ asupra sigurantei codului rezultat. un buton poate ¸ti c˘ trebuie s˘ anunte s a a ¸ un obiect despre faptul c˘ fost ap˘sat. De exemplu. a ıntˆ a a a a Evenimentele ¸i delegatii sunt strˆns legate deoarece r˘spunsul la acest evenis ¸ a a ment se va face de c˘tre un event handler. Un delegat este un tip referint˘ folosit pentru a ˆ ¸a ıncapsula o metod˘ cu un a anumit antet (tipul parametrilor formali ¸i tipul de retur). Evenimente.1 Tipul delegat ˆ programare deseori apare urm˘toarea situatie: trebuie s˘ se execute o In a ¸ a anumit˘ actiune. dar nu va ¸ti aprioric pe cine. care ˆ C# se implementeaz˘ ca a ın a un delegat. Alte evenimente se pot declan¸a independent de s a s actiunile utilizatorului: sosirea unui email. dar nu se ¸tie de dinainte care anume. precum ¸i cu o u¸oar˘ generalizare (vezi ¸ s s a delegatii multicast). Mai a a s degrab˘ decˆt s˘ se lege butonul de un obiect particular. butonul va declara a a a un delegat.Curs 6 Delegati. sau chiar ce obiect va a ¸ s trebui efectiv utilizat. Orice metod˘ care s a are acela¸i antet poate fi legat˘ la un anumit delegat. acest lucru se rezolv˘ prin intermediul pointerilor la funtii. Un eveniment este o ˆ as a a ıncapsulare a ideii c˘ “se ˆ ampl˘ ceva” la care programul trebuie s˘ r˘spund˘. Fiecare actiune pe care utilizatorul o execut˘ pe o interfat˘ grafic˘ de¸ a ¸a a clan¸eaz˘ un eveniment. Delegatii a ¸ ¸ rezolv˘ aceea¸i problem˘. ¸ Structuri 6. ¸ Un delegat este creat dup˘ urm˘toarea sintax˘: a a a 127 . ¸ s sfˆr¸itul unei interog˘ri pe o baz˘ de date.

DELEGATI. WhichIsFirst. ˆ functie a ın ¸ de tipul lor efectiv: de exemplu pentru ni¸te persoane (clasa Student ˆ cele s ın ce urmeaz˘) se va face dup˘ nume. ˆ functie de tipul obiectelor continute. care va ¸a implementa relatia de ordine. //primul obiect din colectie este primul in ordinea sortarii theSecondComesFirst = 1 //al doilea obiect din colectie este primul in ordinea sortarii } Delegatul (tipul de metod˘ care realizeaz˘ compararea) se declar˘ astfel: a a a //declarare de delegat public delegate Comparison WhichIsFirst( object obj1. protected. ¸ Clasa Pair va defini un delegat. public. Clasa Pair se declar˘ dup˘ cum urmeaz˘: a a a .1. EVENIMENTE. object obj2). object obj2). pe cˆnd pentru animale (clasa Dog) se a a a va face dup˘ alt criteriu: greutatea. deci se va folosi pentru s ¸ ele tipul object. Nu ¸ a s se va ¸ti aprioric care va fi tipul obiectelor continute. Dar sortarea celor dou˘ obiecte se va face diferit. fiind de fapt o declaratie de clas˘ derivat˘ din System.128 CURS 6. internal. Rezolvarea se va da prin delegati. cˆt ¸i ˆ exteriorul a ın a s ın ei. Metoda Sort de ordonare va prelua ca (unic) parametru o instant˘ a metodei WhichIsFirst. atunci este ¸i static (a se vedea statutul ın s claselor interioare). STRUCTURI ¸ atributeopt modificatori-de-delegatopt delegate tip-retur identificator( listaparam-formaliopt ).1 Utilizarea delegatilor pentru a specifica metode ¸ la runtime S˘ presupunem c˘ se dore¸te crearea unei clase container simplu numit a a s Pair care va contine dou˘ obiecte pentru care va putea face ¸i sortare. private.Delegate. Exemplu: public delegate int WhichIsFirst(object obj1. Containerul Pair va trebui s˘ fac˘ fat˘ a a a ¸a acestor clase diferite. 6. Un delegat se poate specifica atˆt ˆ interiorul unei clase. Dac˘ ¸ a a a este declarat ˆ interiorul unei clase. a definit de utilizator: public enum Comparison { theFirstComesFirst = 0. Rezul¸ ın ¸ ¸ tatul unei comparatii ˆ ¸ ıntre dou˘ obiecte va fi de tipul enumerare Comparison. Modificatorul de delegat poate fi: new.

thePair[0] = thePair[1].ToString(). } //Ordinea este data de greutate public static Comparison WhichDogComesFirst( 129 .weight=weight. TIPUL DELEGAT public class Pair { //tabloul care contine cele doua obiecte private object[] thePair = new object[2]. } } //metoda ce permite tiparirea perechii curente //se foloseste de polimorfism .ToString()+".thePair[1]) == Comparison. thePair[1] = secondObject. object secondObject) { thePair[0] = firstObject.theSecondComesFirst) { object temp = thePair[0]. } //metoda publica pentru ordonarea celor doua obiecte //dupa orice criteriu public void Sort( WhichIsFirst theDelegatedFunc ) { if (theDelegatedFunc(thePair[0]. "+thePair[1]. } } Clasele Student ¸i Dog sunt: s public class Dog { public Dog(int weight) { this.1. thePair[1] = temp.6. //constructorul primeste cele doua obiecte continute public Pair( object firstObject.vezi mai jos public override string ToString( ) { return thePair[0].

} //studentii sunt ordonati alfabetic public static Comparison WhichStudentComesFirst( Object o1.weight > d2.name.theFirstComesFirst.name = name. return d1. } private int weight. Dog d2 = o2 as Dog. Student s2 = o2 as Student.theFirstComesFirst : Comparison.theSecondComesFirst : Comparison.Compare(s1. } //pentru afisarea greutatii unui caine public override string ToString( ) { return weight. } private string name.weight ? Comparison. return (String. Object o2) { Dog d1 = o1 as Dog. } Clasa de test este: .theSecondComesFirst).130 CURS 6. EVENIMENTE. DELEGATI. STRUCTURI ¸ Object o1.ToString( ). s2. Object o2) { Student s1 = o1 as Student. } public class Student { public Student(string name) { this.name) < 0 ? Comparison. } //pentru afisarea numelui unui student public override string ToString( ) { return name.

WhichStudentComesFirst). studentPair. O modalitate mai bun˘ este s˘ se obtin˘ delegatii direct a a ¸ a ¸ din clasele Student ¸i Dog. TIPUL DELEGAT 131 public class Test { public static void Main( ) { //creaza cate doua obiecte //de tip Student si Dog //si containerii corespunzatori Student Stacey = new Student(‘‘Stacey’’). } } 6. Student Jesse = new Student (‘‘Jess’’).WriteLine(‘‘dogPair\t: {0}’’. Fred). Dog Fred = new Dog(5).1.WriteLine(‘‘studentPair\t: {0}’’. .WhichStudentComesFirst).Sort(theStudentDelegate). Jesse).ToString( )). WhichIsFirst theDogDelegate = new WhichIsFirst(Dog. //sortare folosind delegatii studentPair. Console.WhichDogComesFirst). Pair dogPair = new Pair(Milo. Pair studentPair = new Pair(Stacey.1. Console.6.ToString( )). //Instantiaza delegatii WhichIsFirst theStudentDelegate = new WhichIsFirst(Student. dogPair.Sort(theDogDelegate). dogPair). Console.WriteLine(‘‘Dupa sortarea pe dogPair\t\t: {0}’’. dogPair.2 Delegati statici ¸ Unul din aspectele neelegante ale exemplului anterior este c˘ e necesar ca a ˆ clasa Test s˘ se instantieze delegatii care sunt necesari pentru a ordona ın a ¸ ¸ obiectele din Pair. Console. studentPair). Dog Milo = new Dog(10). Acest lucru se obtine prin crearea unui delegat s ¸ static ˆ interiorul fiec˘rei clase: ın a public static readonly WhichIsFirst OrderStudents = new WhichIsFirst(Student.WriteLine(‘‘Dupa sortarea pe studentPair\t: {0}’’.

se poate s˘ vrei a a a a s˘ efectuezi mai mult de o sigur˘ actiune: s˘ scrii ˆ a a ¸ a ıntr–un textbox un ¸ir s de caractere ¸i s˘ ˆ s a ınregistrezi ˆ ıntr–un fi¸ier faptul c˘ s–a ap˘sat acel buton s a a (logging).. ˆ [2] este dat˘ ¸i o implementare de delegat ca proprietate static˘. STRUCTURI ¸ (analog pentru clasa Dog.. Acest lucru s–ar putea rezolva prin construirea unui vector de delegati care s˘ contin˘ toate metodele dorite. deoarece initilizatosul nu este considerat expresie con¸ stant˘). ¸ a Orice delegat care returnez˘ void este un delegat multicast. EVENIMENTE. De exemplu. studentpair. a ın ın 6. de remarcat c˘ “static readonly” nu se poate a ˆ ınlocui cu “const”. Rezultatul unei astfel de “adun˘ri” este un nou delegat a multicast care la apelare va invoca metodele continute. aceasta In as a ducˆnd la crearea unui delegat doar ˆ cazul ˆ care este nevoie de el1 . DELEGATI. care poate fi a tratat ¸i ca un delegat single-cast.OrderStudent). presupunˆnd c˘ Transmitter este compatibil cu myMulticastDelegate (are a a aceea¸i semn˘tur˘). pentru un astfel de exemplu.3 Multicasting Uneori este nevoie ca un delegat s˘ poat˘ apela mai mult de o singur˘ a a a metod˘.. atunci urm˘toarea linie va produce combinarea lor ˆ a a ıntr–un singur delegat: myMulticastDelegate = Writer + Logger. ˆ a acest lucru ar duce la un ¸ a ¸ a ıns˘ cod greu de urm˘rit ¸i inflexibil. a se vedea [2]. a s pag. . Declaratia de mai sus se folose¸te astfel: a ¸ s ..1.132 CURS 6. Doi delegati multicast pot fi combinati s ¸ ¸ folosind semnul +. dac˘ Writer ¸i Logger sunt delegati care a a s ¸ returneaz˘ void. Mult mai simplu ar fi dac˘ un delegat ar putea s˘ contin˘ a a ¸ a mai mult de o singur˘ metod˘. Operatorul − = functioneaz˘ invers fat˘ de + =. s a a ¸ a ¸a Exemplu: 1 Tehnic˘ numit˘ initializaer tˆrzie (lazy initialization) a a ¸ a . De exemplu.Sort(Student. care va ad˘uga a ¸ a delegatul de la dreapta operatorului la delegatul multicast aflat ˆ stˆnga sa: ın a myMulticastDelegate += Transmitter. Acest lucru se nume¸te multicasting ¸i este a a s s folosit intens la tratarea evenimentelor (vezi sectiunea urm˘toare). 261–265. Se pot ad˘uga delegati multicast folosind operatorul +=. ˆ ordinea ˆ care ¸ ın ın s–a f˘cut adunarea. rezultatul fiind identic. atunci cˆnd un buton este ap˘sat.

//Invoca metoda delegat Writer Writer("String passed to Writer\n"). Transmitter. //declaratia de delegat multicast public delegate void StringDelegate(string s). public class MyImplementingClass { public static void WriteString(string s) { Console. Logger = new StringDelegate( MyImplementingClass.WriteLine("Transmitting string {0}".WriteLine("Logging string {0}". //Invoca metoda delegat Logger 133 .6. } public static void LogString(string s) { Console. //Instantiaza primii trei delegati //dand metodele ce se vor incapsula Writer = new StringDelegate( MyImplementingClass. s). s). s).1. } public static void TransmitString(string s) { Console.TransmitString). //defineste alt delegat //care va actiona ca un delegat multicast StringDelegate myMulticastDelegate. TIPUL DELEGAT using System. Logger.LogString). Transmitter = new StringDelegate( MyImplementingClass.WriteString). } } public class Test { public static void Main( ) { //defineste trei obiecte delegat StringDelegate Writer.WriteLine("Writing string {0}".

//invoca cele trei metode delagate myMulticastDelegate( "Second string passed to Collector"). //anunta utilizatorul ca va combina doi delegati Console. //adauga al treilea delegat myMulticastDelegate += Transmitter. //combina doi delegati.WriteLine( "\nmyMulticastDelegate -= Logger"). //apelaeaza myMulticastDelegate //de fapt vor fi chemate cele doua metode myMulticastDelegate( "First string passed to Collector"). //scoate delegatul Logger myMulticastDelegate -= Logger.WriteLine( "\nmyMulticastDelegate += Transmitter"). STRUCTURI ¸ Logger("String passed to Logger\n"). EVENIMENTE.WriteLine( "myMulticastDelegate = Writer + Logger"). //anunta utilizatorul ca se va scoate delegatul Logger Console.134 CURS 6. //Anunta utilizatorul ca se va adauga al treilea delegat Console. rezultatul este //asignat lui myMulticastDelagate myMulticastDelegate = Writer + Logger. //Invoca metoda delegat Transmitter Transmitter("String passed to Transmitter\n"). } } La ie¸ire vom avea: s Writing string String passed to Writer Logging string String passed to Logger Transmitting string String passed to Transmitter myMulticastDelegate = Writer + Logger Writing string First string passed to Collector Logging string First string passed to Collector myMulticastDelegate += Transmitter Writing string Second string passed to Collector . //invoca cele doua metode delegat ramase myMulticastDelegate( "Third string passed to Collector"). DELEGATI.

2. Butonul va comunica faptul c˘ a fost ap˘sat. ¸ Alte clase pot fi interesate ˆ a r˘spunde la aceste evenimente.2 Evenimente ¸i delegati s ¸ Tratarea evenimentelor ˆ C# se face folosind delegati. 6.2. Nu se poate prezice ordinea ˆ care se a a ın petrec evenimentele. In mod se define¸te o dependent˘ de tip one–to–many ˆ s ¸a ıntre obiecte astfel ˆ at ıncˆ un obiect ˆsi schimb˘ starea. Clasa ce public˘ ın ¸ a define¸te un delegat pe care clasele abonate trebuie s˘ ˆ implementeze. la ap˘sarea unui buton) nu trebuie s˘ ¸tie a a s modul ˆ care se va r˘spunde. etc. terminarea a transferului unui fi¸ier.2 Evenimente Interfetele grafice actuale cer ca un anumit program s˘ r˘spund˘ la eveni¸ a a a mente. pe scurt. Modul ın a ˆ care vor r˘spunde va fi extrem de particular. Butonul va fi numit publicator 2 deoarece publia a c˘ evenimentul Click iar celelalte clase sunt numite abonati 3 deoarece ele a ¸ subscriu la evenimentul Click. Cˆnd s a ıl a evenimentul este declan¸at. Un eveniment poate fi de exemplu ap˘sarea unui buton. un buton poate s˘ notifice un num˘r oarecare de observatori a a atunci cˆnd a fost ap˘sat. a a ıl s a ˆ acest toate obiectele care au subscris la acest eveniment sunt notificate. Cˆnd obiectul care a publicat evenimentul ˆ ¸i semnaleaza˘. orice obiect poate s˘ publice un set de evenimente la care alte clase In a pot s˘ subscrie.2. iar clasa care genereaz˘ ın a a evenimentul (ex: clasa Button.6. toate celelate obiecte dependente sunt notificate ı¸ a ¸i modificate automat. selectarea unui meniu. iar la aparitia unuia se va cere tratarea sa. s De exemplu.1 Publicarea ¸i subscrierea s ˆ C#. EVENIMENTE Logging string Second string passed to Collector Transmitting string Second string passed to Collector myMulticastDelegate -= Logger Writing string Third string passed to Collector Transmitting string Third string passed to Collector 135 6. se ˆ ampl˘ ceva s ıntˆ a la care trebuie s˘ se dea un r˘spuns. ın a a a iar clasele interesate ˆ acest eveniment vor reactiona ˆ consecint˘. ın ¸ ın ¸a 6. metodele claselor abonate vor fi apelate prin s 2 3 Engl: publisher Engl: subscribers .

ˆ conformitate cu metodologia de declarare a unui event handler. extern.minute = minute. this. override. a Clasa Clock va contine o metod˘ Run(): ¸ a . public. Tip este un handler de eveniment (delegat multicast). int minute. Exemplu: public event SecondChangeHandler OnSecondChange. int second ) { this. Vom da mai jos un exemplu care va construi urm˘toarele: o clas˘ Clock a a care folose¸te un eveniment (OnSecondChange) pentru a notifica potentialii s ¸ abonati atunci cˆnd timpul local se schimb˘ cu o secund˘.NET Framework returneaz˘ void ¸i preia doi ¸ ın a s parametri: primul parametru este sursa evenimentului (obiectul publicator). private. astfel ˆ at s˘ se permit˘ mai multi abonati). Tipul TimeInfoEventArgs este definit de noi ca o clas˘ derivat˘ din a a EventArgs: public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs( int hour. ıncˆ a a ¸ ¸ Metodele care r˘spund la un eveniment se numesc event handlers. un event handler ˆ . public readonly int minute. Informatia este a a ¸ ¸ ¸ accesibil˘ readonly. this.136 CURS 6. static.hour = hour. STRUCTURI ¸ intermediul delegatului (pentru care se prevede posibilitatea de a fi multicast. } Aceast˘ clas˘ va contine informatie despre timpul curent. EVENIMENTE. sealed. virtual. Declararea unui eveniment se face astfel: atributeopt modificatori-de-evenimentopt event tip nume–eveniment Modificator-de-eveniment poate fi abstract. public readonly int second. Prin a conventie. al doilea parametru are tip EventArgs sau derivat din acesta. protected. Tipul acestui ¸ a a a eveniment este un delegat SecondChangeHandler care se declar˘ astfel: a public delegate void SecondChangeHandler( object clock.second = second. } public readonly int hour. DELEGATI. pomenit˘ ın a mai sus. TimeInfoEventArgs timeInformation ). new. internal.

se vor a a ¸a notifica toate obiectele abonate dup˘ care ˆsi va modifica starea.DateTime dt = System.Second. } } //modifica timpul curent in obiectul Clock this. this.2. a a Dac˘ timpul s–a schimbat cu o secund˘ fat˘ de timpul precedent.Now().Hour. dt.Minute. dt.Minute.Sleep(10).DateTime.Second). Vor fi dou˘ clase: una numit˘ DisplayClock a a care va afi¸a pe ecran timpul curent ¸i o alta numit˘ LogCurrentTime care s s a ar trebui s˘ ˆ a ınregistreze evenimentul ˆ ıntr–un fi¸ier.hour = dt. prin cele a ı¸ trei atribuiri finale.6. } } Metoda Run creeaz˘ un ciclu infinit care interogheaz˘ periodic ceasul sistem. //daca cineva este abonat.. //daca timpul s-a schimbat cu o secunda //atunci notifica abonatii if( dt. timeInformation). dar pentru simplitate va s afi¸a doar la dispozitivul curent de ie¸ire informatia tranmsis˘: s s ¸ a public class DisplayClock { .minute = dt.second = dt. //obtine timpul curent System. Tot ce r˘mˆne de f˘cut este s˘ se scrie ni¸te clase care s˘ subscrie la evenia a a a s a mentul publicat de clasa Clock.Second != second) //second este camp al clasei Clock { //creeaza obiect TimeInfoEventArgs //ce va fi transmis abonatilor TimeInfoEventArgs timeInformation = new TimeInfoEventArgs(dt. EVENIMENTE 137 public void Run() { for(.Hour. atunci anunta-l if (OnSecondChange != null) { OnSeconChange(this.) { //dormi 10 milisecunde Thread. this.

} } public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.second. DELEGATI. ti. } void TimeHasChanged( object theClock.138 CURS 6.second.ToString( ). EVENIMENTE. using System.OnSecondChange += new Clock. } } De remarcat faptul c˘ evenimentele sunt ad˘ugate folosind operatorul +=. ti. a a Exemplul ˆ ˆ ın ıntregime este dat mai jos: using System. ti. TimeInfoEventArgs ti) { Console.ToString( ).minute.SecondChangeHandler(TimeHasChanged). ti.WriteLine("Logging to file: {0}:{1}:{2}".hour.OnSecondChange += new Clock.Threading.ToString( ).hour. ti.ToString( )).WriteLine("Current Time: {0}:{1}:{2}".ToString( ).SecondChangeHandler(WriteLogEntry).minute. TimeInfoEventArgs ti) { Console. ti. STRUCTURI ¸ public void Subscribe(Clock theClock) { theClock. } //Aceasta metoda ar trebui sa scrie intr-un fisier //dar noi vom scrie la consola void WriteLogEntry( object theClock.ToString( )). //o clasa care va contine informatie despre eveniment //in acest caz va contine informatie disponibila in clasa Clock public class TimeInfoEventArgs : EventArgs { .

this. public readonly int second.minute = minute.DateTime dt = System.Second).Second != second) { //creaza obiectul TimeInfoEventArgs //care va fi transmis fiecarui abonat TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Minute. //evenimentul ce se publica public event SecondChangeHandler OnSecondChange.Hour. int second) { this. public readonly int minute. TimeInfoEventArgs timeInformation ). int minute.DateTime. //citeste timpul curent al sistemului System..second = second.6. //daca cineva a subscris la acest eveniment //atunci anunta-l if (OnSecondChange != null) .dt.Now.2. EVENIMENTE public TimeInfoEventArgs(int hour.dt. 139 } //clasa care publica un eveniment: OnSecondChange //clasele care se aboneaza vor subscrie la acest eveniment public class Clock { //delegatul pe care abonatii trebuie sa il implementeze public delegate void SecondChangeHandler( object clock.) { //inactiv 10 ms Thread. //ceasul este pornit si merge la infinit //va declansa un eveniment pentru fiecare secunda trecuta public void Run( ) { for(. this.Sleep(10). } public readonly int hour. //daca s-a schimbat fata de secunda anterior inregistrata //atunci notifica pe abonati if (dt.hour = hour.

ti.hour = dt. } //handlerul de eveniment de pe partea //clasei DisplayClock void TimeHasChanged( object theClock. ti. STRUCTURI ¸ OnSecondChange(this. DELEGATI.SecondChangeHandler(TimeHasChanged).Minute.second = dt.minute. private int second. } } //modifica starea curenta this. EVENIMENTE.timeInformation).Hour. private int minute.140 { CURS 6.ToString( ). ti. } } private int hour. } //un observator (abonat) //DisplayClock va subscrie la evenimentul lui Clock //DisplayClock va afisa timpul curent public class DisplayClock { //dandu-se un obiect clock.OnSecondChange += new Clock. } } //un al doilea abonat care ar trebui sa scrie intr-un fisier public class LogCurrentTime { public void Subscribe(Clock theClock) .minute = dt. this. va subscrie //la evenimentul acestuia public void Subscribe(Clock theClock) { theClock.Second. this. TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}".second.ToString( )).hour.ToString( ).

//creaza un obiect DisplayClock care //va subscrie la evenimentul obiectului //Clock anterior creat DisplayClock dc = new DisplayClock( ). EVENIMENTE { theClock. //porneste ceasul theClock.second. dc.Subscribe(theClock).2.OnSecondChange += new Clock.Subscribe(theClock).WriteLine("Logging to file: {0}:{1}:{2}". } //acest handler ar trebui sa scrie intr-un fisier //dar va scrie la standard output void WriteLogEntry( object theClock. ti. } } public class Test { static void Main( ) { //creaza un obiect de tip Clock Clock theClock = new Clock( ). } } La ie¸ire se va afi¸a: s s Current Logging Current Logging Time: 14:53:56 to file: 14:53:56 Time: 14:53:57 to file: 14:53:57 141 . TimeInfoEventArgs ti) { Console. ti.6.ToString( )).ToString( ).minute.SecondChangeHandler(WriteLogEntry). ti.Run( ). lct.ToString( ).hour. //analog se creeaza un obiect de tip LogCurrentTime //care va subscrie la acelasi eveniment //ca si obiectul DisplayClock LogCurrentTime lct = new LogCurrentTime( ).

constructori. STRUCTURI ¸ Time: 14:53:58 to file: 14:53:58 Time: 14:53:59 to file: 14:53:59 6. 5.2. ¸ a ¸a . cˆmpuri. public. internal. a a ¸ a ¸ a propriet˘¸i. ¸ ¸ Declaratia unei structuri se face astfel: ¸ atributeopt modificatori-de-structopt struct identificator :interfeteopt corp . Nu poate contine destructor. ¸ La atribuire. se face o copiere a valorilor continute de c˘tre surs˘ ˆ ¸ a a ın destinatie (indiferent de tipul cˆmpurilor: valoare sau referint˘). cˆnd ˆ metoda Run() se poate afi¸a direct pe ecran a ın s sau ˆ ıntr–un fi¸ier informatia cerut˘? Avantajul abord˘rii anterioare este c˘ s ¸ a a a se pot crea oricˆte clase care s˘ fie notificate atunci cˆnd acest eveniment se a a a declan¸eaz˘. ¸i nu o adres˘ de memorie). Clasele abonate nu trebuie s˘ ¸tie despre modul ˆ care lucreaz˘ s a as ın a clasa Clock. a a Publicatorul ¸i abonatii sunt decuplati. constructori statici. metode. de asemenea. este automat considerat˘ sealed a a (sect. iar clasa Clock nu trebuie s˘ ¸tie despre clasele care vor subscrie as la evenimentul s˘u. operatori.3 Comentarii S–ar putea pune urm˘toarea ˆ a ıntrebare: de ce este nevoie de o astfel de redirectare de eveniment. sunt folosite predilect pentru tipuri pentru care aspectul comportamental este mai putin pronuntat. clasele abonate pot s˘ ˆsi ın a ı¸ modifice modul de tratare a evenimentului. indexatori. protected. EVENIMENTE. Sunt considerate versiuni “u¸oare” ale s a s claselor. private.opt ¸ Modificatorii de structur˘ sunt: new. cu principala a a a diferent˘ c˘ sunt tipuri valoare (o astfel de variabil˘ va contine direct val¸a a a ¸ oarea. un buton poate s˘ publice un eveniment OnClick a a ¸i orice num˘r de obiecte pot subscrie la acest eveniment.ValueType. care la rˆndul ei este a a a derivat˘ din System. primind o notificare s a atunci cˆnd butonul este ap˘sat. Similar. O a structur˘ este automat derivat˘ din System.3). evenimente.3 Structuri Structurile reprezint˘ tipuri de date asem˘n˘toare claselor.Object.142 Current Logging Current Logging CURS 6. ¸ a 6. ˆ mod transparent fat˘ de clasa ın ¸a Clock. Clasa Clock poate s˘ modifice s ¸ ¸ a modalitatea de detectare a schimb˘rii de timp f˘r˘ ca acest lucru s˘ impun˘ a aa a a o schimbare ˆ clasele abonate. DELEGATI. Poate ˆ a s˘ implementeze una sau mai multe interfete. Toate aceste caracteristici fac ˆ ıntretinerea codului extrem de facil˘. ıns˘ a ¸ O structur˘ poate s˘ contin˘ declaratii de constante. at tipuri interioare. De asemenea.

Format(‘‘{0}. STRUCTURI Exemplu: using System. } 143 . } public int xVal. yVal = yCoordinate. } set { yVal = value. public int yVal. } public int X { get { return xVal. } set { xVal = value.6. public struct Point { public Point(int xCoordinate. xVal. } } public override string ToString( ) { return (String. } } public int Y { get { return yVal. int yCoordinate) { xVal = xCoordinate.yVal)).3. {1}’’.

100 Loc1 location: 200. 300 Deseori pentru o structur˘ se declar˘ cˆmpurile ca fiind publice. loc1). } } Dup˘ cum este dat ˆ exemplul de mai sus. myFunc(loc1). loc. s-ar fi semnalat o eroare la compilare. folosind propriet˘¸i.X = 50. 300 In MyFunc loc: 50.WriteLine(‘‘Loc1 location: {0}’’. STRUCTURI ¸ public class Tester { public static void myFunc(Point loc) { loc. nu se va crea o instant˘ ˆ memoria ın ¸a ın heap.300). dar ˆ acest caz. se va afi¸a tot valoarea original˘. ci pe stiv˘. crearea unei instante se face a ın ¸ folosind operatorul new . Transmiterea lui loc1 ca parametru se face prin valoare. at a Alte aspecte demne de retinut: ¸ • Cˆmpurile nu pot fi initializate la declarare. DELEGATI. .WriteLine(‘‘Loc1 location: {0}’’. } static void Main( ) { Point loc1 = new Point(200. EVENIMENTE. Alti a ¸ programatori consider˘ ˆ a c˘ accesarea membrilor trebuie s˘ se fac˘ precum a ıns˘ a a a la clase. Console. a adic˘ metoda myFunc nu face decˆt s˘ modifice o copie de pe stiv˘ a lui a a a a loc1. limbajul o sprijin˘. loc). Console. pentru a a a a nu mai fi necesare definirea accesorilor (simplificare implement˘rii).Y = 100. altfel spus. Console. public int yVal = 20. Oricare ar fi alegerea. deoarece loc1 a r˘mas s a a nemodificat: Loc1 location: 200. dac˘ ˆ exema ¸ a ın plul de mai sus se scria: public int xVal = 10.144 CURS 6. La revenire. loc1).WriteLine(‘‘In MyFunc loc: {0}’’.

¸ a • Dac˘ programatorul define¸te un constructor. i++ ) { Console. De asemenea este apelat s la initializarea membrilor unei clase (care se face ˆ ¸ ınainte de orice constructor).6. compilatorul va crea un astfel de constructor. ¸a Pentru tipul Point de mai sus. ¸i duce la crearea a dou˘ puncte cu abcisele ¸i ordonatele 0. a false pentru bool. Point b = new Point(). care va initializa cˆmpurile la ¸ a valorile lor implicite (0 pentru tipuri numerice sau pentru enumer˘ri. • Nu se poate declara destructor. Nu se poate folosi respectiva variabil˘ a de tip structur˘ decˆt dup˘ ce i se initializeaz˘ toate cˆmpurile: a a a ¸ a a Point p. atunci ¸ ın a respectiva instant˘ nu va avea asociat˘ nici o valoare (constructorul im¸a a plicit nu este apelat automat!). va duce la aparitia erorii de compilare: ¸ . urm˘toarea secvent˘ de cod este corect˘: a ¸a a Point a = new Point(0.Length. } va afi¸a de 10 ori puncte de coordonate (0. STRUCTURI 145 • Nu se poate defini un constructor implicit. Acestia se declar˘ numai pentru clase.WriteLine(p). • Dac˘ pentru instantierea unei structuri declarate ˆ interiorul unei a ¸ ın metode sau bloc de instructiuni ˆ general nu se apeleaz˘ new. for( int i=0. i<points. dup˘ care ˆ interiorul lui (¸i nu pe stiv˘!) se creeaz˘ ın a ın s a a cele 10 puncte (alocare inline). Un cons a s structor implicit este apelat atunci cˆnd se creeaz˘ un tablou de struca a turi: Point[] points = new Points[10]. 0).WriteLine(points[i]). null pentru tipuri referint˘). De mentionat pentru exemplul anterior c˘ se creeaz˘ un obiect de tip ¸ a a tablou ˆ heap. atunci acesta trebuie s˘ a s a dea valori initiale pentru cˆmpurile continute. 0). altfel apare eroare la ¸ a ¸ compilare.3. Console. Cu toate acestea.

alte 100 pentru puncte). crearea unui tablou de 100 de elemente de tip Point (de mai sus) va duce la crearea unui singur obiect (tabloul este un obiect). se va face copierea tuturor cˆmpurilor continute pe stiv˘. la transmiterea prin valoare s a unei structuri. ci ˆ ın functie de context) la un overhead datorat conversiei.s’ of type ’MyStruct’ causes a cycle in the stru • Dac˘ o instant˘ este folosit˘ acolo unde un object este necesar. • Dac˘ se ˆ cearc˘ definirea unei structuri care contine un cˆmp de tipul a ın a ¸ a structurii. Dac˘ Point ar fi declarat ca ¸i s ¸ a s clas˘. ar fi fost necesar˘ crearea a 101 instante de obiecte ˆ heap (un obiect a a ¸ ın pentru tablou. ceea ce ar duce la mai mult lucru pentru garbage collector. Dar ˆ cazul ˆ care structurile sunt folosite ˆ colectii (care stocheaz˘ ın ın ın ¸ a object). atunci a ¸a a se va face automat o conversie implicit˘ c˘tre System. STRUCTURI ¸ Use of unassigned local variable ‘p’ Dar dup˘ ni¸te asign˘ri de tipul: a s a p. se va face automat un boxing. .146 CURS 6.3. a ¸ a ceea ce poate duce la un overhead semnificativ.1 Structuri sau clase? Structurile pot fi mult mai eficiente ˆ alocarea memoriei atunci cˆnd sunt ın a retinute ˆ ¸ ıntr–un tablou. utilizarea unei structuri poate duce (dar nu obligatoriu. DELEGATI. EVENIMENTE. De asemenea.yVal=0. iar cele 100 de instante de tip structur˘ ar fi alocate inline ˆ ¸ a ın vectorul creat (¸i nu referinte ale acestora). atunci va ap˘rea o eroare de compilare: a struct MyStruct { MyStruct s.Object (boxing). afi¸area este posibil˘ (practic. } va genera un mesaj din partea compilatorului: Struct member ’MyStruct. De exemplu. orice apel de metod˘ pe instant˘ este s a a ¸a acum acceptat). ¸ 6. ceea ce duce la overhead (memorie ¸i timp = resurse suplimentare).xVal=p. a a Ca atare.

7. Atribute ¸ 7. permite tratarea erorilor ¸i a situatiilor des ¸ osebite prin exceptii.1. a a Chiar dac˘ se scot toate bug–urile.Exception sau In ¸ derivate ale acestuia. Exceptiile nu sunt gˆndite pentru a preveni bug– ¸ a urile (cu toate c˘ un bug poate s˘ duc˘ la aparitia unei exceptii). pentru c˘ a a a ¸ ¸ a acestea din urm˘ ar trebui s˘ fie eliminate. ¸ 1 Si nu neap˘rat a ˆ ¸ a ıntregului proces! 147 . atunci se va arunca o exceptie. precum deschiderea unui fi¸ier al c˘rui nume este gre¸it sau ˆ artiri s a s ımp˘ ¸ la 0. Ea este folosit˘ pentru a semnala contextul ˆ ¸ a a ın care apare situatia deosebit˘ ¸ a Un programator nu trebuie s˘ confunde tratarea exceptiilor cu erorile sau a ¸ bug–urile.1 Tratarea exceptiilor ¸ C#. la fel ca alte limbaje. sau eventual s˘ lase o functie de nivel superior s˘ a a ¸ a ¸ a o trateze. sau se a ¸ pot crea propriile tipuri exceptie. Dac˘ nimeni nu trateaz˘ aceast˘ exceptie. dar se pot manipula astfel ˆ at ¸ ıncˆ nu vor duce la pr˘bu¸irea programului. Un bug este o eroare de programare care ar trebui s˘ fie fixat˘ a a ˆ ınainte de livrarea codului. Exist˘ o ierarhie de exceptii care se pot folosi. atunci CLR o va face. cineva va trebui s˘ sesizeze (s˘ ¸ a ¸ a a “prind˘”) aceast˘ exceptie. O exceptie este un obiect care ˆ ¸ ¸ ıncapsuleaz˘ informatie a ¸ despre o situatie anormal˘. a a a ¸ dar aceasta duce la oprirea thread–ului 1 . Nu se pot preveni astfel de situatii. Cˆnd o metod˘ ˆ alne¸te o situatie a s a a ıntˆ s ¸ exceptional˘.Curs 7 Tratarea exceptiilor. vor exista erori predictibile dar neprea venibile.1 Tipul Exception ˆ C# se pot arunca ca exceptii obiecte de tip System.

1. dup˘ care CLR ¸ s ¸ a ˆ ıncepe s˘ caute un manipulator de exceptie. poate fi de asemenea o a s ¸ adresa Web (URL) • public Exception InnerException {get.148 CURS 7. ajungˆndu–se a ın a at a la metoda apelant˘. Exemplu: MethodBase este o clas˘ care pune la dispozitie informatii despre metodele ¸i cona ¸ ¸ s structorii unei clase 2 . set. a ¸ • public virtual string HelpLink {get. public Exception(string. Fie undeva ˆ lantul de metode care au fost apelate a ın ¸ se g˘se¸te un exception handler.} obtine un mesaj care descrie exceptia ¸ ¸ curent˘ a • public virtual string Source {get. fie thread–ul curent este terminat de c˘tre a s a CLR.} returnez˘ exceptia care este ˆ a ¸ ıncorporat˘ ˆ exceptia curent˘ a ın ¸ a • public virtual string Message {get. o exceptie ın ¸ a ¸ poate deci s˘ contin˘ ˆ interiorul s˘u o instant˘ a altei exceptii (cea a ¸ a ın a ¸a ¸ care a fost de fapt semnalat˘ initial).} obtine o reprezetare string a ¸ apelurilor de metode care au dus la aparitia acestei exceptii ¸ ¸ • public MethodBase TargetSite {get. ultimul preia un obiect de tip Exception (sau de tip clas˘ derivat˘) care va fi ˆ a a ıncapsulat ˆ instanta curent˘. Dac˘ un handler de exceptie a ¸ a ¸ nu este g˘sit ˆ metoda curent˘.constructori. Exception) . set. public Exception(string). TRATAREA EXCEPTIILOR. ATRIBUTE ¸ Enumer˘m urm˘toarele metode ¸i propriet˘¸i relevante ale clasei Excepa a s at tion: • public Exception().} obtine metoda care a aruncat ¸ exceptia curent˘2 ¸ a 7.} obtine sau seteaz˘ un link ¸ a c˘tre un fi¸ier help asociat acestei exceptii. Aruncarea unei exceptii opre¸te executia metodei curente.2 Aruncarea ¸i prinderea exceptiilor s ¸ Aruncarea cu throw Aruncarea unei exceptii se face folosind instructiunea throw.Exception(). Exemplu: ¸ ¸ throw new System.} obtine sau seteaz˘ numele aplicatiei ¸ a ¸ sau al obiectului care a cauzat eroarea • public virtual string StackTrace {get. atunci CLR va cur˘¸a stiva.

’’). Deoarece lipse¸te un event handler ¸ s care s˘ trateze aceast˘ excepctie.WriteLine(‘‘Enter Main.. Console..cs:line 24 at Test.. ci CLR–ul va ˆ ıncepe imediat c˘utarea event handler–ului care a . Console.Exception( ).’’).7. Enter Func2.Test.’’). ˆ metoda Func2() nu se va mai executa a ¸ ın ultima linie.. public class Test { public static void Main( ) { Console.cs:line 12 Deoarece este aruncat˘ o exceptie.Test.’’).. } public void Func1( ) { Console...’’)...WriteLine(‘‘Exit Func2.. Enter Func1.WriteLine(‘‘Exit Main. Func2( ). t..’’). iar la ie¸ire vom avea: a s Enter Main. se va ˆ a a ¸ ıntrerupe thread–ul curent (¸i fiind s singurul.WriteLine(‘‘Enter Func1.cs:line 18 at Test..Exception was thrown at Test. } public void Func2( ) { Console..Func1( ). Exception occurred: System.WriteLine(‘‘Enter Func2.Test...Main( ) in . ¸i ˆ s ıntregul proces) de c˘tre CLR...WriteLine(‘‘Exit Func1. TRATAREA EXCEPTIILOR ¸ using System. Test t = new Test( )..Func1( ) in .1......Func2( ) in . } } 149 Se exemplific˘ apelul de metode: Main() apeleaz˘ Func1(). Console.Exception: An exception of type System. care apeleaz˘ a a a Func2(). aceasta va arunca o exceptie. throw new System..

.WriteLine(‘‘Exit Main.... Console.WriteLine(‘‘Enter Func1. Func2( ).’’).’’). La fel.. } Console.WriteLine(‘‘Enter Func2.. } public void Func2( ) { Console.’’). ATRIBUTE ¸ s˘ trateze exceptia..Func1( ). Console. throw new System.WriteLine(‘‘Exception caught and handled.’’). nu se execut˘ nici ultima linie din Func1() sau a ¸ a din Main().WriteLine(‘‘Exit Func1..WriteLine(‘‘Exit Func2. Prinderea cu catch Prinderea ¸i tratarea exceptiei se poate face folosind un bloc catch. Test t = new Test( ). } catch { Console..’’). TRATAREA EXCEPTIILOR. public class Test { public static void Main( ) { Console..WriteLine(‘‘Enter Main..’’).. } public void Func1( ) { Console. t..’’). } } . creat s ¸ prin intermediul instructiunii catch.WriteLine(‘‘Entering try block.WriteLine(‘‘Exiting try block. try { Console.’’)..150 CURS 7. Console.’’)...Exception( ). ¸ Exemplu: using System.

restul vor duce la aparitia exceptiei. Enter Func1.WriteLine(‘‘Exit Main..WriteLine(‘‘Enter Func1..... Se observ˘ c˘ ˆ blocul catch nu s–a specificat tipul de exceptie care se a a ın ¸ prinde..’’). } . public class Test { public static void Main( ) { Console. Console. La ¸ a ie¸ire se va afi¸a: s s Enter Main. CLR–ul nu va mai opri procesul..1. Console..’’).. executia nu se va relua de la a ¸ a ¸ instructiunea care a produs exceptia.. Func2( ). Test t = new Test( )..WriteLine(‘‘Enter Main. Exit Func2..WriteLine(‘‘Exiting try block. Exemplu: ın ¸ a using System.. Uneori. Entering try block.. Chiar dac˘ exceptia este tratat˘.’’). In ¸ ¸ ın a ¸ instructiunilor din blocul try se ignor˘ ¸i controlul este preluat de c˘tre blocul ¸ as a catch... Exit Func1. t. Exit Main..7... ci se continu˘ cu instructiunea de dup˘ ¸ ¸ a ¸ a blocul catch. Exception caught and handled.Func1( ).WriteLine(‘‘Entering try block... prinderea ¸i tratatarea exceptiei nu se poate face ˆ functia apelat˘.. asta ˆ ınseamn˘ c˘ se va prinde orice exceptie se va arunca. indiferent a a ¸ de tipul ei.’’).. try { Console..’’). } public void Func1( ) { Console. Enter Func2. TRATAREA EXCEPTIILOR ¸ 151 Se observ˘ c˘ s–a folosit un bloc try pentru a delimita instructiunile care a a ¸ ˆ momentul ˆ care se arunc˘ exceptia. Deoarece exceptia a fost tratat˘. s ¸ ın ¸ a ci doar ˆ functia apelant˘.

..Exception( ). Exception caught and handled. ca mai sus.152 CURS 7. ˆ functie de natura st˘rii ap˘rute. Enter Func1. pentru a fi consultat˘ mai tˆrziu). am vrea ca ˆ functie de a ın ¸ natura exceptiei aruncate... s˘ facem o tratare anume. Console.. Este posibil ca ˆ ıntr–o secvent˘ de instructiuni s˘ se arunce mai multe tipuri de ¸a ¸ a ˆ acest caz. s a a Acest lucru se face specificˆnd tipul exceptiei care ar trebui tratate ˆ a ¸ ın blocul catch: using System.WriteLine(‘‘Exit Func2... t. ATRIBUTE ¸ catch { Console. In ¸ ın ¸ a a ¸ printr–un bloc catch generic.’’). Entering try block.. } } La ie¸ire se va afi¸a: s s Enter Main.WriteLine(‘‘Exception caught and handled. nu este util˘.. } Console. Enter Func2. deoarece ˆ majoritatea a a ¸ a ın cazurilor este necesar s˘ se cunoasc˘ natura erorii (de exemplu pentru a fi a a scris˘ ˆ a ıntr-un fi¸ier de logging.. Exit Func1.’’)... throw new System.WriteLine(‘‘Enter Func2..’’). TRATAREA EXCEPTIILOR. Exit Main.. Se sugereaza chiar s˘ nu ¸ a a se foloseasc˘ aceast˘ constructie de prindere generic˘. } .TestFunc( ).’’).WriteLine(‘‘Exit Func1. } public void Func2( ) { Console... prinderea exceptiei exceptii.. public class Test { public static void Main( ) { Test t = new Test( )..

} //Tipul mai general de exceptie este ultimul catch { Console.ArithmeticException.b)). iar primul tip care ın ın se potrive¸te cu exceptia aruncat˘ (ˆ sensul c˘ tipul exceptie specificat este s ¸ a ın a ¸ . Console. return a/b. } //cel mai derivat tip de exceptie se specifica primul catch (System. a. double b = 0. if (a == 0) throw new System. TRATAREA EXCEPTIILOR ¸ 153 //incearca sa imparta doua numere public void TestFunc( ) { try { double a = 5.7.DivideByZeroException.DivideByZeroException) { Console.1.WriteLine(‘‘DivideByZeroException caught!’’). Este a a ¸ ¸ posibil˘ specificarea mai multor blocuri de tratare a exceptiilor.WriteLine(‘‘Unknown exception caught’’).ArithmeticException) { Console.ArithmeticException( ). b. } catch (System.DivideByZeroException( ). } } //efectueaza impartirea daca se poate public double DoDivide(double a.WriteLine (‘‘{0} / {1} = {2}’’.WriteLine(‘‘ArithmeticException caught!’’). } } ˆ exemplul de mai sus s–a convenit ca o ˆ artire cu numitor 0 s˘ duc˘ la In ımp˘ ¸ a a o execeptie System. double b) { if (b == 0) throw new System. Aceste a ¸ blocuri sunt parcurse ˆ ordinea ˆ care sunt specificate. DoDivide(a. iar o ˆ artire cu num˘r˘tor 0 ¸ ımp˘ ¸ aa s˘ duc˘ la aparitia unei exceptii de tip System.

WriteLine (‘‘Close file here. ar trebui s˘ existe o a a a garantie c˘ un anumit cod se va executa. Ca atare. este ¸ a important ca ordinea exceptiilor tratate s˘ fie de la cel mai derivat la cel mai ¸ a general. } finally { Console. t. System. TRATAREA EXCEPTIILOR. De exemplu. Blocul finally Uneori. double b = 0. a.TestFunc( ). ¸ care se va executa ˆ orice situatie. Console. ¸ as a a Exemplu: using System. aruncarea unei exceptii ¸i golirea stivei pˆn˘ la blocul de tratare ¸ s a a a exceptiei poate s˘ nu fie o idee bun˘. Acest lucru se face prin intermediul blocului finally. b.WriteLine(‘‘Open file here’’). public class Test { public static void Main( ) { Test t = new Test( ). Existenta acestui bloc elimin˘ necesitatea ın ¸ ¸ a existentei blocurilor catch (cu toate c˘ ¸i acestea pot s˘ apar˘). Console. dac˘ exceptia apare ¸ a a a ¸ atunci cˆnd un fi¸ier este deschis (¸i ˆ a s s ınchiderea lui se poate face doar ˆ ın metoda curent˘). ˆ exemplul anterior.’’).DivideByZeroException este derivat In din clasa System.WriteLine (‘‘This line may or may not print’’). } public void TestFunc( ) { try { Console.b)).WriteLine (‘‘{0} / {1} = {2}’’. double a = 5. ATRIBUTE ¸ fie exact tipul obiectului aruncat. fie un tip de baz˘ al acestuia . Altfel spus.din cauz˘ a a de upcasting) este cel care va face tratarea exceptiei ap˘rute. } .ArithmeticException. atunci ar fi util ca s˘ se ˆ a a ınchid˘ fi¸ierul ˆ a s ınainte ca s˘ fie a preluat controlul de c˘tre metoda apelant˘. DoDivide(a.154 CURS 7. indiferent dac˘ totul merge normal ¸ a a sau apare o exceptie.

mesajul “Close file here” se va afi¸a indiferent de ce In s parametri se transmit metodei DoDivide().com’’.7.greselifatale. TRATAREA EXCEPTIILOR ¸ } public double DoDivide(double a. e. } iar cˆnd exceptia este prins˘. if (a == 0) throw new System. care este derivat˘ direct din Sysa tem. Se indic˘ aceast˘ derivare deoarece astfel se face distinctie a a ¸ ˆ ıntre exceptiile aplicatie ¸i cele sistem (cele aruncate de c˘tre CLR). public class MyCustomException : System.HelpLink = ‘‘http://www.ArithmeticException( ).HelpLink).ApplicationException { public MyCustomException(string message): base(message) .WriteLine( ‘‘DivideByZeroException! goto {0} and read more’’.1. e. ¸ ¸ s a Exemplu: using System. return a/b.DivideByZeroException e) { Console. se poate prelucra informatia: a ¸ a ¸ catch (System. throw e.ApplicationException. double b) { if (b == 0) throw new System. } Crearea propriilor exceptii ¸ ˆ cazul ˆ care suita de exceptii predefinite nu este suficient˘. } } 155 ˆ exemplul de mai sus. programIn ın ¸ a atorul ˆsi poate construi propriile tipuri. La aruncarea unei exceptii se poate particulariza obiectul care se arunc˘: ¸ a if (b == 0) { DivideByZeroException e = new DivideByZeroException( ).DivideByZeroException( ). Se recomand˘ ca acestea s˘ fie ı¸ a a derivate din System.Exception.

156 { } } CURS 7.WriteLine(‘‘HelpLink: {0}’’. b.HelpLink). ATRIBUTE ¸ public class Test { public static void Main( ) { Test t = new Test( ). e. } } . Console. Console.WriteLine(‘‘\nMyCustomException! Msg: {0}’’.DivideByZeroException e) { Console.WriteLine (‘‘{0} / {1} = {2}’’. } catch { Console. } catch (System. e.WriteLine(‘‘DivideByZeroException! Msg: {0}’’.b)). e.HelpLink). TRATAREA EXCEPTIILOR. double b = 5. t.Message).WriteLine (‘‘This line may or may not print’’). } catch (MyCustomException e) { Console.TestFunc( ). e. Console.WriteLine(‘‘\nHelpLink: {0}\n’’.WriteLine(‘‘Unknown exception caught’’). Console. } public void TestFunc( ) { try { double a = 0.Message). DoDivide(a. a.

Dac˘ ¸ s ¸ a a se dore¸te ca aceast˘ exceptie s˘ p˘streze cumva ˆ interiorul ei exceptia s a ¸ a a ın ¸ original˘. atunci constructorul permite ˆ a ınglobarea unei referinte la aceasta. .htm’’. throw e.HelpLink = ‘‘http://www.Exception inner): base(message. e. } } Rearuncarea exceptiilor ¸ Este perfect posibil ca ˆ ıntr–un bloc de tratare a exceptiilor s˘ se se fac˘ ¸ a a o tratare primar˘ a exceptiei.com’’. ¸ aceast˘ referint˘ va fi accesibil˘ prin intermediul propriet˘¸ii InnerException: a ¸a a at using System. throw e.greselifatale. dup˘ care s˘ se arunce mai departe o alt˘ a ¸ a a a exceptie.HelpLink= ‘‘http://www.inner) { } } public class Test { public static void Main( ) { Test t = new Test( ).7.1. e.greselifatale. } if (a == 0) { MyCustomException e = new MyCustomException( ‘‘Can’t have zero divisor’’).com/NoZeroDivisor. } return a/b.ApplicationException { public MyCustomException(string message. public class MyCustomException : System. TRATAREA EXCEPTIILOR ¸ 157 public double DoDivide(double a. de acela¸i tip sau de tip diferit (sau chiar exceptia original˘). double b) { if (b == 0) { DivideByZeroException e = new DivideByZeroException( ).

} } } public void DangerousFunc1( ) { try { DangerousFunc2( ). TRATAREA EXCEPTIILOR. e.InnerException.Message).TestFunc( ).158 t. } catch(System.e).InnerException. CURS 7. Exception inner = e.WriteLine(‘‘{0}’’.WriteLine(‘‘Retrieving exception history.DivideByZeroException e) { . ATRIBUTE ¸ } public void TestFunc( ) { try { DangerousFunc1( ).Message). inner = inner.’’).inner. } catch (MyCustomException e) { Console.WriteLine(‘‘\n{0}’’... } } public void DangerousFunc2( ) { try { DangerousFunc3( ). while (inner != null) { Console. } catch (System.Exception e) { MyCustomException ex = new MyCustomException(‘‘E3 Custom Exception Situation!’’. Console. throw ex.

Exception) { Console. Un alt exemplu clasic este cazul ˆ care autorul unei metode ¸tie c˘ ın s a o operatie poate s˘ e¸ueze periodic – de exemplu din cauza unui timeout pe ¸ a s retea – dar vrea s˘ reˆ ¸ a ıncerce operatia de n ori ˆ ¸ ınainte de a semnala eroare. numele este introdus gre¸it si se dore¸te ca s˘ se permit˘ corectarea s s a a numelui. } 159 } public void DangerousFunc3( ) { try { DangerousFunc4( ).1.ArithmeticException) { throw.1.3 Reˆ ıncercarea codului Se poate pune ˆ ıntrebarea: cum se procedeaz˘ dac˘ se dorec¸te revenirea a a s la codul care a produs exceptia. } catch (System.7. TRATAREA EXCEPTIILOR ¸ Exception ex = new Exception(‘‘E2 .’’). Urm˘torul exemplu permite unui utia a a lizator s˘ specifice de maxim trei ori numele unui fi¸ier ce se proceseaz˘. ın . throw ex.Func2 caught divide by zero’’. } } 7. } catch (System.WriteLine(‘‘Exception handled here.DivideByZero Exception"). dup˘ tratarea ei? Exist˘ destule situatii ˆ ¸ a a ¸ ın care reexecutarea acestui cod este dorit˘: s˘ ne gˆndim de exemplu la cazul a a a ˆ care ˆ ın ıntr-o fereastr˘ de dialog se specific˘ numele unuei fi¸ier ce trebuie a a s procesat.e). } } public void DangerousFunc4( ) { throw new DivideByZeroException("E1 . cu a s a revenire ˆ cazul erorii. ˆ aceast˘ situatie se poate defini o etichet˘ ˆ In a ¸ a ınaintea blocului try la care s˘ se permit˘ salutl printr–un goto.

WriteLine(). attempts+1). string s.Write("\n[Attempt #{0}] Specify file " + "to open/read: ".Write("Do you want to select " + "another file: ").ReadLine(). string fileName = Console. using System.ReadLine())) { Console.WriteLine(s). while (null != (s = sr.ToUpper(). Console. ATRIBUTE ¸ static void Main() { StreamReader sr. int attempts = 0. if (response == "Y") goto GetFile. TRATAREA EXCEPTIILOR. } sr. if (++attempts < maxAttempts) { Console. response = response. int maxAttempts = 3.WriteLine(e.IO. . try { sr = new StreamReader(fileName).ReadLine(). GetFile: Console.Close().Message).160 using System. class Retry { CURS 7. } catch(FileNotFoundException e) { Console. string response = Console.

atunci nici m˘car nu se mai ajunge a ıns˘ a ¸ a la apel de B. tratarea exceptiilor este superioar˘ acestei tehnici din mai a ¸ a multe motive. . Dac˘ de exemplu pentru o anmit˘ procesare se apeleaz˘ metoda A a a a (de exemplu o deschidere de fi¸ier) dup˘ care metoda B (citirea din fi¸ier). nu se permite o propagare a erorilor. apelul lui B ın a a a ın este deja sortit e¸ecului.Message). se s a s poate ca ˆ A s˘ apar˘ o eroare care nu este luat˘ ˆ considerare.1.ReadLine().1. } } 7.4 Compararea tehnicilor de manipulare a erorilor Metoda standard de tratare a aerorilor a fost ˆ general returnarea unui ın cod de eroare c˘tre metoda apelant˘.7.WriteLine(e.Write("You have exceeded the maximum " + "retry limit ({0})". Neconsiderarea codului de retur Apelul unei functii care returneaz˘ un cod de eroare poate fi f˘cut ¸i f˘r˘ ¸ a a s aa a utiliza efectiv codul returnat. scriind doar numele functiei cu parametrii ¸ de apel. ¸ Altfel spus. TRATAREA EXCEPTIILOR ¸ 161 } else { Console. } } catch(Exception e) { Console. apelantul are sarcina de a a a descifra acest cod de eroare ¸i s˘ reactioneze ˆ consecint˘. Dac˘ ˆ a metoda A arunc˘ o exceptie. Ca atare. pentru c˘ buna sa functionare depinde de efectele lui s a ¸ A. maxAttempts). } Console. ˆ a a¸a cum s a ¸ ın ¸a Ins˘ s se arat˘ mai jos. deoarece CLR-ul va pasa executia unui bloc catch/finally.

a ¸ se presupune c˘ se define¸te un tip exceptie sau o ierarhie de exceptii creat˘ a s ¸ ¸ a convenabil). aruncˆnd exceptii cu mesaje de eroare ex¸ a ¸ plicite sau exceptii de un anumit tip (definit de programator) se poate trata ¸ mult mai convenabil o situatie deosebit˘. Ca atare. programatorii trebuei s˘ declare c˘ o metod˘ poate arunca o In a a a exceptie ¸i s˘ o declare explicti ˆ ¸ s a ıntr–o list˘ astfel ˆ at un apelant s˘ ¸tie a ıncˆ a s c˘ se poate se poate a¸tepta la primirea ei. Folosirea exceptiilor este ˆ acest caz a ¸ ın aproape de neˆ ınlocuit. de corectat ¸i extins. deoarece a ¸ a un constructor nu returneaz˘ valori. TRATAREA EXCEPTIILOR. In s ¸ solutia va contine cod de prelucrare a continutului mixat cu cod de verificare ¸ ¸ ¸ ¸i reactie pentru diferitele cazuri de exceptie. a s a tratarea erorii din exteriorul lui A este dificil˘ ˆ acest caz. . unui fi¸ier folosind coduri de eroare returnate sau exceptii. se poate scrie un cod care realizeaz˘ procesarea continutului ¸ a ¸ ˆ primul caz. .1. deoarece ar trebui a ın s˘ se cerceteze toate codurile de eroare posibile pentru a determina motivul a aparitiei erorii. Aceast˘ cunoa¸tere ˆ avans a s a s ın permite conceperea unui plan de lucru cu fiecare dintre ele. Tehnica verific˘rii codului de retur nu mai functioneaz˘ aici. In a a a 3 Total Cost of Ownership. .NET se sugereaz˘ s˘ se prind˘ oricare dintre ele cu un catch generic. introduc¸ a a a erea apelului lui Bn+1 ˆ interiorul lui A nu reclam˘ modificare suplimenın a tar˘. . U¸urinta citirii codului s ¸ Pentru comparatie.5 Sugestie pentru lucrul cu exceptiile ¸ ˆ Java. preferabil decˆt a ˆ cazul . costul mentinerii a ¸ codului cre¸te permanent. atunci orice apel al lui A trebuie s˘ includ˘ suplimentar ¸i verificarea a a s pentru posibilitatea ca Bn+1 s˘ fi cauzat o eroare. Bn . Codul ˆ al doilea caz este mult s ¸ ¸ ın mai scurt. ATRIBUTE ¸ Manipularea erorii ˆ contextul adecvat ın ˆ cazul ˆ care o metod˘ A apeleaz˘ alte metode B1 . ceea ce are un impact negativ asupra TCO-ului3 s Folosind tratarea exceptiilor. deoarece tipul de exceptie aruncat de Bn+1 este deja tratat (desigur. 7. s ınt ¸ s Aruncarea de exceptii din constructori ¸ Nimic nu opre¸te ca o situatie deosebit˘ s˘ apar˘ ˆ s ¸ a a a ıntr–un apel de constructor.162 CURS 7. de mentinut. mai u¸or de ˆ ¸eles. Mai mult decˆt atˆt. Dac˘ se mai adauga ¸i apelul de metod˘ Bn+1 ˆ interiorul ¸ a s a ın lui A. este posibil ca In ın a a oricare din aceste n metode s˘ cauzeze o eroare (¸i s˘ returneze cod adecvat).

1 Generalit˘¸i at Atributele sunt de dou˘ feluri: intrinseci (predefinite) ¸i definite de utia s lizator. metode.1: Tintele atributelor.NET. ATRIBUTE 163 s˘ se mentin˘ o documentatie cu exceptiile care poti fi aruncate de fiecare a ¸ a ¸ ¸ metod˘.1 contine ¸intele posibile ¸i o scurt˘ descriere a lor. ¸ 7. anumite atribute predefinite sunt utilizate pentru a specifica dac˘ a un tip este sau nu serializabil. delegati. a Unde ar fi utile aceste atribute? Exemple de utilizare a lor ar fi urm˘rirea a bug–urilor care exist˘ ˆ a ıntr–un sistem sau urm˘rirea stadiului proiectului. tipuri de date continute. Metadata este o dat˘ ¸ ¸ s a despre assembly (versiune. parametri.2 Atribute O aplicatie . Cele intrinseci sunt integrate ˆ platforma . Aceste comentarii ¸ a ˆ a nu vor fi incluse ˆ bytecod-ul final. at Tinta unui atribut specific˘ cui anume i se va aplica un atribut anume. doar ˆ eventuala documentatie. proa a ¸ priet˘¸i. valori de retur. interfete. ¸ enumer˘ri. ¸ Tint˘ ¸ a All Assembly ClassMembers Class Constructor Descriere Orice element Un assembly Orice membru al unei clase O clas˘ a Un constructor . clase. module. evenimente. a 7. ¸ ¸ informatii despre versiunea assembly-ului. ¸ a Tabelul 7. etc.2. structuri. a Atributele sunt folosite pentru a da o extra-informatie compilatorului ¸ de . ¸ t s a Tabelul 7. metode. Java folose¸te o combinatie de semne /** ¸i @ pentru a include s ¸ s informatie relativ la clase.NET contine cod. date ¸i metadate. constructori. etc ¸ stocate ˆ ımpreun˘ cu codul compilat. Atributele se pot specifica pentru: assembly–uri. care sunt portiunile de cod scoase din circulatie. cˆmpuri sau parametri.NET ¸i sunt recunoscute ın s de CLR. aceast˘ informatie poate fi stocat˘ ˆ codul compilat ¸i a ¸ a ın s reutilizat˘ ulterior la runtime. cˆmpuri. ıns˘ ın ın ¸ Folosind atributele. Atributele definite de utilizator sunt create ˆ functie de dorintele ın ¸ ¸ acestuia. De a asemenea. producator.7.2. etc).

specificarea unui atribut se face a In prin scrierea lui imediat ˆ ınaintea elementului asupra c˘ruia se aplic˘: a a using System. fie ˆ a ın interiorul acelora¸i paranteze. specificarea lor se face dup˘ toate declaratiile ın a a ¸ using.1 (continuare) Descriere Un delegat O enumerare Un eveniment Un cˆmp a O interfat˘ ¸a O metod˘ a Un modul Un parametru O proprietate O valoare de retur O structur˘ a Tint˘ ¸ a Delegate Enum Event Field Interface Method Module Parameter Property ReturnValue Struct Aplicarea atributelor se face prin specificarea numelui lor ˆ ıntre paranteze drepte. Webservice] ˆ cazul atributelor ce se specific˘ pentru un assembly.2 prezint˘ cˆteva dintre ele: a a . ATRIBUTE ¸ Tabelul 7.164 CURS 7. Exemplu: s a¸ a [Serializable] [Webservice] echivalent cu: [Serializable. [Serializable] class ClasaSerializabila { //definitia clasei } 7. forma lor este: In a [assembly:AssemblyDelaySign(false)] ˆ cazul acestor din urm˘ atribute. ˆ general. mai multe atribute fie se specific˘unul deasupra celuilalt.2 Atribute predefinite Tabelul 7. TRATAREA EXCEPTIILOR. desp˘rtite prin virgul˘.2. dar ˆ ınaintea oric˘rui cod.

Web.NonSerializedAttribute [NonSerialized] Permite unor membri s˘ nu fie a salvati pe retea sau pe disc ¸ ¸ System.Web. Atribut System.Services.SerializableAttribute [Serializable] 165 Descriere Permite unei clase s˘ fie serializat˘ a a pe disc sau ˆ ıntr–o retea ¸ System.Services.ObsoleteAttribute [Obsolete] Marcheaz˘ o secvent˘ ca fiind scoas˘ a ¸a a din uz System.2: Atribute predefinite.Attribute.WebMethodAttribute Marcheaz˘ o metod˘ ca fiind expus˘ a a a [WebMethod] ca parte a unui serviciu Web System. namespace AttributeSample1 { class Class1 { [STAThread] static void Main(string[] args) { int s1 = AddTwoNumbers(2.CLSCompliant Indic˘ dac˘ un element de program este a a [CLSCompliant] compatibil cu CLS System. 3). a a Exemplul de mai jos folose¸te atributul System.Reflection.WebServiceAttribute Permite specificarea unui nume ¸i a s [WebService] unei descrieri pentru un serviciu Web System. 3). 3. s using System.ObsoleteAttribute. 4).AttributeUsageAttribute Define¸te parametrii de utilizare s [AttributeUsage] pentru atribute System.2.AssemblyVersionAttribute Specific˘ num˘rul de versiune al a a [AssemblyVersion] unui assembly System.7. ATRIBUTE Tabelul 7. } [Obsolete("obsolete: use AddNumbers instead")] .Runtime. int s3 = AddNumbers(2. int s2 = AddNumbers(2. specific˘ locatia DLL care contine a ¸ ¸ DllImportAttribute [DllImport] implementarea pentruo metod˘ extern˘ a a ˆ Intre parantezele drepte se arat˘ cum se specific˘ acel atribut.InteropServices.

Binary. } class MyMainClass { public static void Main() { Point2D My2DPoint = new Point2D(). } static int AddNumbers(params int[] numbers) { int result = 0. s pentru atributul Obsolete se poate specifica dac˘ respectivul avertisment este a sau nu interpretat ca o eroare. My2DPoint.Create("Point2D.Formatters. Suplimentar. int b) { return a + b. ATRIBUTE ¸ static int AddTwoNumbers(int a. public int Y.IO. true pentru ca utilizarea s˘ fie tratat˘ a a a ca o eroare. My2DPoint.166 CURS 7. [Serializable] class Point2D { public int X.bin").Runtime. Mesajul specificat ca a a a a parametru al atributului este afi¸at ca mesaj al avertismentului. return result. TRATAREA EXCEPTIILOR. BinaryFormatter BinaryWrite = new BinaryFormatter(). using System. foreach(int number in numbers) result += number.Serialization. . using System. Exemplul de mai jos exemplific˘ serializarea ¸i deserializarea unui obiect: a s using System.Y = 200. Stream WriteStream = File.X = 100. ad˘ugˆnd un parametru de tip bool: false ca la a a compilare s˘ se genereze avertisment. } } } La compilarea codului se genereaz˘ un avertisment care semnalizeaz˘ faptul a a c˘ se utilizeaz˘ o metod˘ care este scoas˘ din uz.

7. WriteStream.Y). Stream ReadStream = File. {1})".Y). ATRIBUTE 167 BinaryWrite. Point2D ANewPoint = new Point2D().Close(). namespace CondAttrib { class Thing { private string name. BinaryFormatter BinaryRead = new BinaryFormatter().Close(). My2DPoint). {1})".X.name = name. SomeFunc(). Console. } } 7. Exemplu: using System.3 Exemplificarea altor atribute predefinite Atributul Conditional Acest atribut se ata¸eaz˘ la o metod˘ pentru care se dore¸te ca atunci s a a s cˆnd compilatorul o ˆ alne¸te la un apel. dac˘ un anumit simbol nu e definit a ıntˆ s a atunci nu va fi chemat˘.bin").Diagnostics.WriteLine("New Point Before Deserialization: ({0}. ANewPoint. ANewPoint.2. Este folosit˘ pentru a omite anumite apeluri de a a metode ( de exemplu cele folosite la etapa de debugging). ANewPoint = (Point2D)BinaryRead.WriteLine("SomeFunc"). Console. ReadStream. public Thing(string name) { this. } public void SomeFunc() { Console. } [Conditional("DEBUG")] .Deserialize(ReadStream).Serialize(WriteStream.2. ANewPoint. using System. SomeDebugFunc(). ANewPoint.OpenRead("Point2D.WriteLine("New Point After Deserialization: ({0}.X.

De exmplu. dar dac˘ rea ¸ a a a spectiva clas˘ este declarat˘ ca fiind CLSCompliant atunci acestea ar trebui a a . Dac˘ un assembly este marcat a a ca fiind CLSCompliant. } } public class Class1 { [STAThread] static void Main(string[] args) { Thing t = new Thing("T1"). Dac˘ la compilare simbolul nu este definit atunci compilatorul va ignora a apelurile de metode calificate cu atributul Conditional. } } } Definirea unui anumit simbol (de exemplu DEBUG) se poate face ˆ dou˘ ın a moduri: • prin folosirea unei directive de preprocesor de tipul #define: #define DEBUG • prin folosirea parametrilor din linia de comanda sau a posibilit˘¸ilor at mediului integrat de dezvoltare.168 CURS 7.WriteLine("SomeDebugFunc"). pentru a se defini un anumit simbolul din Visual Studio se procedeaz˘ astfel: clic dreapta a ˆ Solution Explorer pe numele proiectului. orice tip expus public ˆ assembly care nu este comın patibil CLS trebuie s˘ fie marcat cu CLSCompliant(false). Pe linia Conditional Compilation Constants se adaug˘ simbolul dorit. cˆt ¸i din inspectia codului IL a a ¸ a s ¸ rezultat la compilare. CLS a prevede faptul c˘ tipurile de date ˆ a ıntregi ar trebui s˘ fie cu semn. ATRIBUTE ¸ public void SomeDebugFunc() { Console. selectare Properties apoi ın Configuration Properties. TRATAREA EXCEPTIILOR. Atributul CLSCompliant Acest atribut se aplic˘ pe assembly–uri. metode) de tip unsigned. De exemplu. Acest lucru se paote verifica atˆt urm˘rind executia programului. O clas˘ a a poate s˘ contin˘ membri (cˆmpuri. Acest lucru va avea ca efect folosirea optiunii a ¸ define a compilatorului.

2. Dac˘ ele sunt expuse ˆ a ın afara assembly–ului. } } } } Dac˘ se compileaz˘ assembly-ul de mai sus atunci apare o eroare: a a Type of ’DemoCLS. .ComplianceTest.7. Pentru a ajuta dezvoltatorii . regulile CLS nu se aplica private uint a = 4. ATRIBUTE 169 declarate ca fiind ne-vizibile din afara assembly–ului. astfel. unele limbaje . se va at genera o eroare sau se vor ignora asemenea cazuri. platforma a ¸ pune la dispozitie atributul CLSCompliant cu care se controleaz˘ r˘spunsul ¸ a a compilatorului la expunerea entit˘¸ilor ne-compatibile cu CLS. avem //incompatibilitate CLS public uint B = 5. Exemplu: [assembly:CLSCompliant(true)] namespace DemoCLS { public class ComplianceTest { //Tipul uint nu ste compatibil CLS //deaorece acest camp este privat.B’ is not CLS-compliant Pentru ca aceast˘ eroare s˘ nu mai apar˘ putem s˘ declar˘m B ca fiind a a a a a invizibil din exteriorul assembly-ului sau s˘ ad˘ug˘m inaintea lui B atributul: a a a [CLSCompliant(false)] Meritul acestui atribut este c˘ anunt˘ programatorul despre eventualele neconcordante a ¸a ¸ cu Common Language Specifications.NET s-ar putea s˘ nu le poat˘ folosi efea a tiv. //Acesta este modul corect de expunere a unui uint: //tipul long este compatibil CLS public long A { get { return a.NET s˘ evite asemenea situatii. //deoarece acest camp uint este public.

se mai pot specifica valorile propriet˘¸ilor Inhera at a at ited ¸i AllowMultiple.NET. denumirea ei ˆ conformitate cu anumite reguli (recomandat. atributele predefinite acoper˘ marea majoritate a situatiilor In a ¸ care cer utilizarea de atribute. a ¸ s Valoarea implicit˘ este false. dar a ın nu obligatoriu). adic˘ a elementelor c˘rora li se poate ata¸a. a Exist˘ cˆteva situatii ˆ care e benefic˘ definirea de noi atribute.Attribute fie direct. Valoarea s a a a implicit˘ este true. Sunt cˆ¸iva pa¸i care a at s trebuie parcur¸i pentru realizara unui atribut: specificarea ¸intei.Method. Exema a ¸ ın a plul cel mai des ˆ alnit este acela ˆ care pentru a se mentine informatii ıntˆ ın ¸ ¸ despre un cod la care lucreaz˘ mai multe echipe. Eventualizatea ca utilizatorul s˘ doreasc˘ a a crearea propriilor sale atribute este prev˘zut˘ de c˘tre platforma . se define¸te un atribut care a s s˘ serveasc˘ la pasarea de informatie relativ la portiuni din cod.2. a a a dˆndu–se posibilitatea definirii lor. Un alt a a ¸ ¸ exemplu este utilizarea unui sistem de urm˘rire a stadiului de dezvoltare a a codului. Tintele sunt a a a s ¸ cele din tabelul 7. s Proprietatea Inherited este de tip boolean ¸i precizeaz˘ dac˘ atributul s a a poate fi mo¸tenit de c˘tre clasele derivate din cele c˘reia i se aplic˘.4 Atribute definite de utilizator ˆ general. Pasul 1. metoda. cu posibilitate de repetare a sa: [AttributeUsage(AttributeTargets. clasa. care sunt de fapt valori din enumerarea AttributeTargets. fie indirect. a Proprietatea AllowMultiple este de asemenea de tip boolean ¸i specific˘ s a dac˘ se pot utiliza mai multe instante ale atributului pe un acela¸i element.170 CURS 7.Class | AttributeTargets. AllowMultiple=true)] Pasul 2. ¸ a ın Un atribut utilizator este o clas˘ definit˘ ca pˆn˘ acum. a Vom defini mai jos ¸inta atributului pe care ˆ vom construi ca fiind t ıl assembly–ul. Declararea ¸intei t Primul pas ˆ crearea unui atribut utilizator este specificarea domeniului ın s˘u de aplicabilitate. definirea clasei. t Pe lˆng˘ ¸inta propriu–zis˘. Specificarea ¸intei se face prin intermediul unui (meta)atribut AttributeUsage. urm˘toarele reguli trebuie s˘ fie a a avute ˆ vedere: ın . Declararea unei clase atribut Pentru declarearea unei clase atribut. ATRIBUTE ¸ 7. TRATAREA EXCEPTIILOR. care ar folosi informatia stocat˘ ˆ atribute.1. Se cere a fi a a a a derivat˘ din System. derivarea ei s t adecvat˘.Assembly|AttributeTargets.

7. a [AttributeUsage(AttributeTargets. [AttributeUsage(AttributeTargets. at using System.Method. ATRIBUTE 171 • (obligatoriu) O clas˘ atribut trebuie s˘ deriveze direct sau indirect Sysa a tem. Vom considera a ın a c˘tributul pe care ˆ cre˘m va purta trei informatii: numele programatorua ıl a ¸ lui care a actionat asupra respectivei unit˘¸i de cod.Attribute { private string name. ¸ at ın a optional note. la care particip˘ mai multe echipe. string phase) { this. public CodeTrackerAttribute(string name. this. Acest a atribut utilizator va fi inclus ˆ codul compilat ¸i distribuit altor echipe (care ın s nu vor avea acces la cod). AllowMultiple=true)] public class CodeTrackerAttribute : System. Declararea constructorilor ¸i a propriet˘¸ilor s at Acest pas const˘ ˆ definirea efectiv˘ membrilor clasei. faza ˆ care se afl˘. O alternativ˘ ar fi folosirea documentattiei XML a ¸ generate dup˘ comentariile din cod. private string phase.Attribute { //aici e codul dumneavoastra } Pasul 3. a a Vom declara clasa atribut CodeTrackerAttribute. Acest atribut s-ar putea folosi ˆ cazul ˆ care s-ar dori urm˘rirea dezvolt˘rii codului ˆ cadrul unui ın ın a a ın proiect de dimensiuni foarte mari.Assembly|AttributeTargets.phase = phase.Attribute • (obligatoriu) O clas˘ atribut trebuie s˘ fie declarat˘ ca fiind public˘ a a a a • (recomandat) Un atribut ar trebui s˘ aib˘ sufixul Attribute.2.Class | AttributeTargets. private string notes. al treilea poate fi setat prin intermediul unei propriet˘¸i.Method. AllowMultiple=true)] public class CodeTrackerAttribute : System.Class | AttributeTargets. Primele dou˘ atribute sunt mandatorii ¸i vor fi preluate prin ¸ a s constructor.Assembly|AttributeTargets. } .name = name.

} set{notes=value. s . } } O inspetie a codului IL rezultat arat˘ c˘ aceste atribute s-au salvat ˆ ¸ a a ın codul compilat. "April 1st 2005")] public void SayHello(String message) { Console.} } public virtual string Notes { get{return notes.WriteLine(message).} } } Pasul 4. TRATAREA EXCEPTIILOR. } [CodeTracker("Lucian Sasu". "implementing specification".WriteLine("AttribTest instance"). Utilizarea atributului utilizator Atributele definite de utilizator sutn folosite ˆ acela¸i mod ca ¸i cele ın s s implicite. Obtinerea acestor atribute ¸i a valorilor lor se poate face ¸ s foarte u¸or prin reflectare.} } public virtual string Phase { get{return phase. Notes = "First attempt")] class AttribTest { public AttribTest() { Console. Codul de mai jso exemplific˘ acest lucru: a [CodeTracker("Lucian Sasu".172 CURS 7. ATRIBUTE ¸ public virtual string Name { get{return name.

ADO. integrarea cu XML.NET 8. dar dac˘ num˘rul a s ¸ a a acestora cre¸te aplicatia poate s˘ reactioneze extrem de lent s ¸ a ¸ • pentru unele servere se impun clauze asupra num˘rului de conexiuni ce a se pot folosi simultan.Curs 8 ADO. Toate acestea fac ca ADO.NET Framework ce pera a mite aducerea. Lucrul se poate face fie conectat. ˆ mod normal. dar de asemenea un fi¸ier text sau Exa a s cel sau XML sau Access.NET s˘ fie o tehnologie mai potrivit˘ pentru deza a voltarea aplicatiilor Internet decˆt cele precedente (e. 173 . ¸ ¸ O bun˘ parte a l˘¸imii de band˘ este mentinut˘ ocupat˘ pentru ni¸te a at a ¸ a a s proces˘ri care nu necesit˘ neap˘rat conectare continu˘ a a a a • probleme legate de scalabilitatea aplicatiei: se poate ca serverul de baze ¸ de date s˘ lucreze u¸or cu 5-10 conexiuni mentinute. o surs˘ s In a de date poate s˘ fie o baz˘ de date. reprezentarea comun˘ a datelor cu a posibilitatea de a combina date din variate surse. fie deconectat de la sursa de date.NET? a ADO. manipularea ¸i modificarea datelor.1 Ce reprezint˘ ADO.NET. ADO.NET reprezint˘ o parte component˘ a lui . ¸ a Pentru o prezentare a metodelor de lucru cu surse de date sub platform˘ a Windows se poate consulta [7].NET se impune tocmai prin faptul c˘ permite lucrul deconectat a de la baza de date. ODBC). De¸i exist˘ variate modalit˘¸i de lucru cu bazele de s a at date. Faptul c˘ se permite lucrul deconectat de la sursa de date rezolv˘ urm˘toarele a a a probleme: • mentinerea conexiunilor la baza de date este o operatie costisitoare. toate pe baza unor clase .g.

NET ın Din cauza existentei mai multor tipuri de surse de date (de exemplu. t a Exist˘ urm˘torii furnizori de date2 (lista nu este complet˘): a a a Tabelul 8.2 Furnizori de date ˆ ADO. 8. a 8. DataAdapter . Nume furnizor Prefix API ODBC Data Odbc Provider OleDb Data OleDb Provider Oracle Data Provider SQL Data Provider Borland Data Provider Oracle Sql Bdp Descriere Surse de date cu interfat˘ ODBC ¸a (baze de date vechi) Surse de date care expun o interfat˘ ¸a OleDb.NET const˘ ˆ patru componente: Cona ın nection. Oracle Prefixele trecute ˆ coloana ”Prefix” sunt folosite pentru clasele de lucru ın specifice unui anumit furnizor ADO. Command.microsoft. Toate aceste clase implementeaz˘ ni¸te interfete bine stabilite.0. IBM DB2.com/sql/msde/downloads/download. ca a s ¸ atare trecerea de la un SGBD la altul se face cu eforturi minore (dac˘ codul a este scris ¸inˆnd cont de principiile POO).1: Furnizori de date. Pentru lucrul cu MS SQL Server se poate instala gratuit versiunea gratuit˘ de Microsoft SQL Server 2000 Desktop Engine1 . SQL Server. ADO.0 SGBD Oracle Pentru interactiune cu Microsoft SQL ¸ Server 7. 2000.NET: de exemplu. a ¸ mai multor produc˘tori de servere de baze de date) e nevoie ca pentru fiecare a tip major de protocol de comunicare s˘ se foloseasc˘ o bibliotec˘ specializat˘ a a a a de clase. pentru o connexiune SQL se va folosi clasa SqlConnection. 2005 sau MSDE Acces generic la SGBD-uri precum Interbase.174 CURS 8.NET este 1 2 Adresa: http://www.asp Engl: Data Providers . de exemplu Access ¸i Excel sau s SQL Sever versiune mai veche de 7. DataReader.NET Vom exemplifica ˆ cele ce urmeaz˘ preponderent pe baz˘ de date Miın a a crosoft SQL 2000. Arhitectura ADO.3 Componentele unui furnizor de date Fiecare furnizor de date ADO.

etc. cum ar fi locatia sursei de date. Ele contin date specifice conexiunii.8. a .1 Clasele Connection Sunt folosite pentru a reprezenta o conexiune la surse de date specifice. nu¸ ¸ mele ¸i parola contului de acces.3. 8. ˆ plus au metode pentru deschiderea s In ¸i ˆ s ınchiderea conexiunilor.1: Principalele clase ADO.NET Mai jos sunt date descrieri succinte ale claselor cel mai des utilizate. COMPONENTELE UNUI FURNIZOR DE DATE prezentat˘ ˆ figura 8.3.1 a ın 175 Figura 8. pornirea unei tranzactii sau setarea perioadei de ¸ time-out. Stau la baza oric˘rei ˆ a ıncerc˘ri de conectare.

Prezint˘ at s a a marele avantaj c˘ poate sa lucreze deconectat de la sursa de date.4 Clasele DataAdapter Ultima component˘ principal˘ a unui furnizor de date .NET este DataAdapter. s s a 8.NET. Ele permit scrierea de interog˘ri SQL parametrizate a sau specificarea parametrilor pentru procedurile stocate.5 Clasa DataSet Aceast˘ clas˘ nu este parte a unui furnizor de date .3 Clasele DataReader Permit navigarea de tip forward–only. DELETE) ¸i pentru a furniza un obiect de tip s DataReader sau DataSet. Se obtin pe baza unui obiect de tip Command prin apelul metodei ¸ ExecuteReader(). ¸tergere. Folose¸te serviciile unui obiect de tip DataAdapter pentru as ¸i procura datele ¸i a trimite modific˘rile ˆ s s a ınapoi c˘tre baza de date. Accesul rezultat este extrem de rapid cu minim de resurse consumate. permitˆnd efectuarea operatiilor pe baza de date. apoi reflectarea acestor modific˘ri ˆ s a ın baza de date. acela¸i format este folosit pentru ın s transportul datelor. Pot fi folosite pentru apelarea de proceduri stocate aflate pe server.4 Obiecte Connection Clasele de tip Connection pun la dispozitie tot ceea ce e necesar pentru ¸ conectarea la baze de date. modificare ¸i ad˘ugare la baza de date.3. Contin referinte c˘tre ¸a ¸ ¸ ¸ a obiecte de tip Connection ¸i deschid / ˆ s ınchid singure conexiunea la baza de date.2 Clasele Command Sunt folosite pentru a executa diferite comenzi pe baza de date (SELECT. 8. ADO.3. 8. UPDATE. ˆ a a a Inainte . 8. Un obiect DataSet este de fapt un container de tabele ¸i relatii s ¸ ˆ ıntre tabele. INSERT. un DataAdapter contine referinte c˘tre patru comenzi pentru In ¸ ¸ a selectare.NET ci independent˘ a a a de particularit˘¸ile de conectare ¸i lucru cu o baz˘ de date anume.NET 8.3.3. facilitˆnd a a stocarea ¸i modificarea datelor local. a a Functioneaz˘ ca o punte ˆ ¸ a ıntre sursa de date ¸i obiecte de tip DataSet deconecs tate. read–only ˆ mod conectat la sursa ın de date. Datele a sunt stocate de un DataSet ˆ format XML.176 CURS 8. Este primul obiect cu care un programator ia contact atunci cˆnd ˆ a ıncearc˘ s˘ foloseasc˘ un furnizor de date . ˆ plus.

Data.4.. 8.xls) implementeaz˘ a s a IDbConnection.Jet..Password=parola").0 pentru fi¸ier Acs cess) precum ¸i locul unde se afl˘ sursa de date (C:\Lucru\Northwind.Data.Data Source= C:\Lucru\Northwind.0.mdb). clasele SqlConnection (folosit˘ pen¸ a tru conectare la server Microsoft SQL Server 2000) sau OleDbConnection (folosit˘ pentru conectare la fi¸iere .mdb").mdb din Access sau . . OBIECTE CONNECTION 177 ca o comand˘ s˘ fie executat˘ pe o baz˘ de date trebuie stabilit˘ o conexiune a a a a a la ea.//spatiul de nume SqlClient .Open(). OleDbConnection cn = new OleDbConnection( @"Provider=Microsoft. contul SQL cu care se face accesul (”sa”) ¸i parola pentru s acest cont (”parola”).1 Propriet˘¸i at 1.. Orice clas˘ de tip conexiune (din orice furnizor de date) implementeaz˘ a a intefata IDbConnection.. De exemplu..8.OLEDB. cu accesori de get ¸i set. metode ¸i evenimente pentru un at s obiect de tip Connection. Pentru deschiderea unei conexiuni se poate proceda ca mai jos: using System. ConnectionString: de tip String.OleDb.Jet. baza de date la care se face conectarea (”Northwind”).SqlClient.Open().4. SqlConnection cn = new SqlConnection("Data Source=serverBD. S-a specificat furnizorul de date (Microsoft. s a Vom enumera principalele propriet˘¸i.User ID=sa. cn.OLEDB. Pentru conectarea la un fi¸ier Access Northwind.mdb aflat ˆ directorul s ın c:\lucru se folose¸te un obiect de tipul OleDbConnection sub forma: s using System.4. Mai sus s–a specificat numele calculatorului pe care se afl˘ instalat severul a MSSQL de baze de date (”serverBD”)... aceast˘ pros a prietate define¸te un string valid care permite identificarea tipului ¸i s s locatiei sursei de date la care se face conectarea ¸i eventual contul si ¸ s ..//spatiul de nume OleDb .4. cn. . Database=Northwind.

separati prin punct ¸ ¸i virgul˘. Open. cu accesor de get. 5. Connect Timeout=30"). Valorile posibile sunt: Broken. dar se sugereaz˘ s˘ nu se procedeze ˆ acest mod. s a a a a ın 3. Fetching. a Connecting.178 CURS 8. s • Initial Catalog (sinonim cu Database): specific˘ numele baze de a date. Executing. a 6. Se poate specifica o valoare diferit˘ de 15 ˆ ¸ a ın ConnectionString folosind parametrul Connect Timeout: SqlConnection cn = new SqlConnection("Data Source=serverBD. returneaz˘ furnizorul OLE a DB. ADO. Acest furnizor trebuie precizat doar dac˘ se folose¸te OLE a s DB . State: atribut de tip enumerare ConnectionState . valoare implicit˘ a 15. read-only. a 2. • Data Source: se specific˘ numele serverului de baze de date sau a numele fi¸ierului de date. Provider : atribut de tip string. ServerVersion: atribut de tip string. Closed. specific˘ num˘rul de secunde pentru care un obiect de conexiune a a ar trebui s˘ a¸tepte pentru realizarea conect˘rii la server ˆ a s a ınainte de a se genera o exceptie. read-only. Acest string contine lista de parametri necesari pen¸ tru conectare sub forma numeParametru=valoare. ConnectionTimeout: de tip int. Se poate specifica pentru Connect Timeout valoarea 0 cu semnificatia ¸ ”a¸teapt˘ oricˆt”. .NET Data Provider. returneaz˘ numele bazei de a date la care s–a f˘cut conectarea. • User ID: specifica un nume de utilizator care are acces de loginare la server. 4.User ID=sa. Database: atribut de tip string. ˆ a nu se specific˘ pentru conectare la ıns˘ a SQL Server. Database=Northwind. read-only. returneaz˘ a starea curent˘ a conexiunii. Parametrii sunt: s a • provider : se specific˘ furnizorul de date pentru conectarea la sursa a de date. Baza de date trebuie s˘ se g˘seasc˘ pe serverul dat ˆ Data a a a ın Source.NET parola de acces. Folosit˘ pentru a ar˘ta unui utilizator a a a care este baza de date pe care se face operarea. read-only. returneaz˘ versiunea a de server la care s–a f˘cut conectarea. • Password : specific˘ parola contului de mai sus.Password=parola.

8. structura fi¸ierului XML de a In s configurare este similar˘. a ¸ a 8. Dispose(): ˆ ınchid conexiunea ¸i elibereaz˘ toate resursele alos a cate pentru ea 3. as a 4. fi¸ierul este de tip XML.4 Stocarea stringului de conexiune ˆ fi¸ier de conın s figurare ˆ general este contraindicat ca stringul de conexiune s˘ fie scris direct ˆ In a ın cod. implicit acesta avˆnd numele App.3 Evenimente Un obiect de tip conexiune poate semnala dou˘ evenimente: a • evenimentul StateChange: apare atunci cˆnd se schimb˘ starea conexa a iunii.4. ¸ specifice aplicatiei. OBIECTE CONNECTION 179 8. iar pentru aplicatiile Windows acest fi¸ier s ¸ ¸ s nu exist˘ implicit. Close(). dar se adaug˘ prin click dreapta pe proiect ˆ Solution a a ın Explorer->Add->Add New Item->Application Configuration File. Pentru aplicatiile Web fi¸ierul se ¸ s ¸ s nume¸te web.config. Implicit. Noua baz˘ de date trebuie s˘ existe pe acela¸i server ca precedenta. pentru aplicatiile de tip consol˘ fi¸ierul de configurare are s ¸ a s extensia config ¸i numele aplicatiei. Event-handlerul este de tipul delegat StateChangeEventHandler. Open(): deschide o conexiune la baza de date 2.4. ¸ la sfˆr¸it se apeleaz˘ Commit() sau Rollback(). . a a s 5.4. BeginTransaction(): pentru executarea unei tranzactii pe baza de date.NET Framework permite mentinerea unor perechi de tipul chei-valoare.config. ChangeDatabase(): se modific˘ baza de date la care se vor face conexiua nile.2 Metode 1. ¸ a 8. CreateCommand(): creeaz˘ un obiect de tip Command valid (care ima plementeaz˘ interfata IDbCommand ) asociat cu conexiunea curent˘. modificarea datelor de conectare (de exemplu parola pe cont sau sursa de date) ar ˆ ınsemna recompilarea codului. acesta arat˘ astfel: a a . care spune care sunt st˘rile ˆ a ıntre care s–a f˘cut tranzitia.4. ˆ fie care caz. a ¸ • evenimentul InfoMessage: apare atunci cˆnd furnizorul trimite un avera tisment sau un mesaj informational c˘tre client.

acest num˘r fiind a a 3 Engl: connection pooling .5 Gruparea conexiunilor Gruparea conexiunilor3 reprezint˘ reutilizarea resurselor de tip conexia une la o baz˘ de date. using System. } } 8.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="constring" value="Data Source=serverBD.Data. ADO.Close(). pwd=parola"/> </appSettings> </configuration> Clasele neceasre pentru accesarea fi¸ierului de configurare se g˘sesc ˆ spatiul s a ın ¸ de nume System. Atunci cˆnd se creeaz˘ o grupare de conexiuni se a a a genereaz˘ automat mai multe obiecte de tip conexiune. public class UsingConfigSettings { public static void Main() { SqlConnection con = new SqlConnection( ConfigurationSettings.180 <?xml version="1.SqlClient.Configuration.0" encoding="utf-8" ?> <configuration> </configuration> CURS 8.User ID=sa.database=Northwind. using System.Configuration. precum mai jos: <?xml version="1.4. using System.NET ˆ interiorrul elementului r˘d˘cin˘ configuration se va introduce elementul In a a a appSettings.AppSettings["constring"]). Utilizarea stringului de conexiune definit anterior se face astfel: using System. //se lucreaza cu conexiunea con.Data. care va contine oricˆte perechi cheie-valoare ˆ interiorrul unui ¸ a ın atribut numit add.

1 Propriet˘¸i at 1. con). Un asemenea obiect este folosit pentru a executa comenzi pe baza de date: SELECT. OBIECTE COMMAND 181 egal cu minimul setat pentru gruparea respectiv˘. Dac˘ a¸teparea a s a s dureaz˘ mai mult decˆt este precizat ˆ valoarea de Timeout se va arunca o a a ın exceptie. contine comanda SQL ¸ sau numele procedurii stocate care se execut˘ pe sursa de date. reprezint˘ num˘rul a a de secunde care trebuie s˘ fie a¸teptat pentru executarea interog˘rii. La dorint˘ t ¸ ¸a comportamentul implicit se poate modifica prin intemediul continutului stringu¸ lui de conectare. O nou˘ conexiune este a a creat˘ dac˘ toate conexiunile sunt ocupate ¸i se cere o nou˘ conexiune. a 2.NET trebuie s˘ implea a a menteze interfata IDbCommand. atunci se arunc˘ o exceptie. ¸ a Se observ˘ c˘ obiectul de conexiune este furnizat comenzii create. INSERT. a Exemplu: SqlConnection con = new SqlConnection( ConfigurationSettings.5 Obiecte Command Un clas˘ de tip Command dat˘ de un furnizor . 8. doarece locatia sursei de date se specific˘ doar la conexiune. cu diferenta c˘ ˆ loc de SqlCommand se folose¸te OleDa a ¸ a ın s bCommand. ci se va pune ˆ a ıntr–o coad˘ de a¸teptare. Enua a mer˘m mai jos principalele propriet˘¸i ¸i metode ale unui obiect de tip coa at s mand˘. a as a ¸ . DELETE. a s a Dac˘ se dep˘¸este acest timp. ca atare toate vor asigura un set de servicii ¸ bine specificat.AppSettings["constring"]). CommandTimeout: de tip int. a 8.NET administreaz˘ automat acest aspect. degrevˆndu-l a a pe programator de aceast aspect ce nu ¸ine de logica aplicatiei.Data. Nu trebuie modificat ¸ altceva. Dac˘ a a s a a dimensiunea maxim setat˘ a grup˘rii este atins˘. UPDATE sau apel de proceduri stocate (dac˘ SGBD-ul respectiv ¸tie acest lucru). Pentru a returna o conexiune la grupare trebuie apelat˘ metoda ¸ a Close() sau Dispose() pentru acea conexiune. Comanda se poate a s executa numai dac˘ s-a deschis o conexiune la baza de date. CommandText: de tip String. SqlCommand cmd = new SqlCommand("SELECT * FROM Customers".8. Codul care utilizeaz˘ o comand˘ pentru lucrul cu fisiere mdb sau xls ar fi a a foarte asem˘n˘tor. din spatiul de nume System.5. cu ambii accesori. Sursele de date . cu ambii accesori. atunci nu se va mai crea a a a o conexiune nou˘.5.OleDb.

NET Data Provider].Data. SqlConnection con.[. dac˘ proprietatea CommandType are aceast˘ valoare. ADO. read-write.NET Data Provider].proprietate de tip System. de exemplu un obiect SqlCommand se poate obtine astfel: ¸ SqlCommand cmd. “Prefix” este prefixul asociat furnizorului respectiv (a se vedea tabelul 8.NET 3. 5. SqlConnection con ). cu ambii accesori.proprietate de tip System. Data.proprietate de tip System. Parameters . cmd = new SqlCommand(string CommandText).interpreteaz˘ comanda ca fiind o comand˘ a a SQL clasic˘. a • CommandType. reprezint˘ tipul de comand˘ care se execut˘ pe sursa de date. atunci proa a prietatea CommandText este interpretat˘ ca numele unui tabel a pentru care se aduc toate liniile ¸i coloanele la momentul exes cut˘rii.Text .interpreteaz˘ comanda continut˘ a ¸ a ˆ proprietatea CommandText ca o un apel de procedur˘ stocat˘ ın a a definit˘ ˆ baza de date. aceast˘ list˘ a fost creat˘ prin apelul a a a metodei CreateParameter(). a 4.NET Data Provider]. contine obiectul de tip conexiune ¸ folosit pentru legarea la sursa de date. Connection . PrefixTransaction.2 Metode 1. CommandType: de tip CommandType (enumerare). a ın • CommandType.“Prefix” reprezint˘ acelasi lucru ca mai sus. Valorile a a a pot fi: • CommandType. cu ambii accesori. a 6. .StoredProcedure . returneaz˘ o colectie de parametri a ¸ care s-au transmis comenzii. SqlTransaction trans). PrefixConnection. cmd = new SqlCommand(string CommandText. [. cmd = new SqlCommand(string CommandText. Constructori .[.un obiect de tip comand˘ poate fi creat ¸i prin intera s mediul apelului de constructor.Data. permite accesul la obiectul de tip tranzactie ¸ care se cere a fi executat pe sursa de date.1). read-only.5. PrefixParameterCollection. cmd = new SqlCommand().182 CURS 8. Transaction .momentan disponibil numai pentru furnizorul OLE DB (deci pentru obiect de tip OleDbCommand).TableDirect . 8.

Dispose() . se returneaz˘ num˘rul de ˆ a a ınregistr˘ri afectate. sau aceast˘ ˆ a a ın ¸ a ıncercare nu are nici un efect nu se intˆmpl˘ nimic.ExecuteReader().g.ExecuteNonQuery().CommandText = "DELETE FROM Customers WHERE CustomerID = ’SEVEN’".AppSettings["constring"]). a DELETE.distruge obiectul comand˘. Exemplu: se obtine continutul tabelei Customers ˆ ¸ ¸ ıntr–un obiect de tip SqlDataReader (se presupune c˘ baza de date se stocheaz˘ pe un server a a MSSQL): SqlConnection con = new SqlConnection( ConfigurationSettings. Cancel() . a a a a a a ın ¸ Dac˘ nu se afl˘ ˆ executie. SqlCommand cmd = new SqlCommand(). se a a arunc˘ o exceptie de tip InvalidOperationException. UPDATE. SqlCommand cmd = new SqlCommand(). OBIECTE COMMAND 183 2. cmd.execut˘ o comand˘ care nu returneaz˘ un set de a a a date din baza de date.CommandText = "SELECT * FROM Customers". SqlDataReader reader = cmd. while(reader.8. cmd. cmd. a 4. cmd. ExecuteReader() .Connection = con.5. a a 3. Console.ToString()). con. a ¸ Exemplu: SqlConnection con = new SqlConnection( ConfigurationSettings.Connection = con.Close() ˆ exemplul de mai sus se returneaz˘ num˘rul de ˆ In a a ınregistr˘ri care au a fost ¸terse.Open(). Dac˘ nu este a a definit˘ conexiunea la baza de date sau aveasta nu este deschis˘. con.ˆ ıncearc˘ s˘ opreasc˘ o comand˘ dac˘ ea se afl˘ ˆ executie.Read()) { . ExecuteNonQuery() . dac˘ comanda a fost de tip INSERT. Sqls a DataReader sau OleDbDataReader ).AppSettings["constring"]).Open(). s 5.execut˘ comanda continut˘ ˆ proprietatea Coma ¸ a ın mandText ¸i se returneaz˘ un obiect de tip IDataReader (e. con.WriteLine(cmd.

{1}". 7. 6. Acest mod permite ˆ arcarea sub forma unui flux ınc˘ de date folosind GetChars() sau GetBytes(). atunci s–ar returna doar prima ˆ ınregistrare din setul de date.execut˘ comanda continut˘ ˆ proprietatea Coma ¸ a ın mandText.SingleRow). s a • CommandBehavior. ExecuteScalar() .CloseConnection . • CommandBehavior.comanda returnez˘ informatie dea ¸ spre coloane ¸i cheia primar˘.SingleResult . De a a exemplu. ExecuteXmlReader() .WriteLine("{0} . ADO. reader.returneaz˘ un obiect de tipul XmlReader obtinut a ¸ din rezultatul interog˘rii pe sursa de date. a Exemplu: . } reader.NET Metoda ExecuteReader() mai poate lua un argument optional de tip ¸ enumerare CommandBehavior care descrie rezultatele ¸i efectul asupra s bazei de date: • CommandBehavior. folosit pentru obtinerea unor rezultate de tip ¸ agregat (“SELECT COUNT(*) FROM CUSTOMERS”.KeyInfo .SchemaOnly .GetString(0).GetString(1)). • CommandBehavior.se returneaz˘ o singur˘ linie. de exemplu).comanda returnez˘ doar informatie a ¸ despre coloane. reader.conexiunea este ˆ ınchis˘ atunci a cˆnd obiectul de tip IDataReader este ˆ a ınchis.se returneaz˘ un singur set de a rezultate • CommandBehavior. CURS 8.SingleRow .Close(). • CommandBehavior.ExecuteReader( CommandBehavior. con.Close().184 Console. dac˘ ˆ codul anterior ˆ a ın ınainte de while obtinerea obiec¸ tului reader s–ar face cu: SqlDataReader reader = cmd.SequentialAccess . se returneaz˘ valoarea primei coloane de pe primul rˆnd a a a setului de date rezultat.d˘ posibilitatea unui DataReader a s˘ manipuleze ˆ a ınregistr˘ri care contin cˆmpuri cu valori binare de a ¸ a mare ˆ ıntindere.

5. } reader.Close(). con). t Exemplu: vom aduce din tabela Customers toate ˆ ınregistr˘rile care au ˆ a ın cˆmpul Country valoarea “USA”. con).5.CommandType = CommandType. proceduri stocate) a a pe server care s˘ fie parametrizate. con. ELEMENTS". while(reader. cmd.GetDecimal(1)). reader.Open().Xml. Orice furnizor de date . printr-un apel de tipul con. 8.5.NET permite a crearea obiectelor parametru care pot fi ad˘ugate la o colectie de parametri a ¸ ai comenzii. SqlCommand cmd = new SqlCommand("Ten Most Expensive Products".WriteLine("{0} .ExecuteXmlReader().4 Folosirea comenzilor parametrizate Exist˘ posibilitatea de a rula cod SQL (interog˘ri. a SqlConnection con = new SqlConnection( .8.Read()) { Console.AppSettings["constring"]). reader.{1}".ExecuteReader(). Daca conexiunea a fost folosit˘ pentru un obiect de tip DataRead atunci acesta din urm˘ a a trebuie s˘ fie ¸i el ˆ a s ınchis. Dac˘ nu se face acest a apel atunci conexiunea va fi ¸inut˘ ocupat˘ ¸i nu va putea fi reutilizat˘.GetString(0). SqlDataReader reader = cmd. OBIECTE COMMAND 185 SqlCommand custCMD=new SqlCommand("SELECT * FROM Customers FOR XML AUTO.Close(). System. ˆ ınaintea ˆ ınchiderii conexiunii. con.3 Utilizarea unei comenzi cu o procedur˘ stocat˘ a a Pentru a se executa pe server o procedur˘ stocat˘ definit˘ ˆ baza respeca a a ın tiv˘. este necesar ca obiectul comand˘ s˘ aibe proprietatea CommandType la a a a valoarea CommandType. Valoarea cestor parametrii se specific˘ fie prin numele lor (cazul a SqlParameter ).StoredProcedure. fie prin poziˇia lor (cazul OleDbParameter ). Observatie: se remarc˘ ˆ toate exemplele de mai sus faptul c˘ fiecare conex¸ a ın a iune se ˆ ınchide manual. t a as a 8.StoredProcedure iar proprietatea CommandText s˘ a contin˘ numele procedurii stocate: ¸ a SqlConnection con = new SqlConnection( ConfigurationSettings.Close().XmlReader myXR = custCMD.

{1}".Value.ExecuteReader(). ADO. cmd. param.VarChar).GetString(1)).Value = "USA". SqlParameter param = new SqlParameter("@country". reader.Parameters.GetString(1)).Parameters. cmd.ToString()).Close(). acest lucru trebuie spus In ın s explicit folosind proprietatea Direction a parametrului respectiv: SqlCommand cmd = new SqlCommand( "SELECT * FROM Customers WHERE Country = @country. } reader.WriteLine("{0} . SqlDbType. "Count".Value = "USA". Console.186 CURS 8.WriteLine("{0} .Int)). Pentru parametrul creat s–a setat tipul lui (ca fiind tip SQL ¸ir de caracs tere) ¸i valoarea.Add(new SqlParameter("@count".Add( param ).WriteLine("{0} . con. SqlDataReader reader = cmd. while(reader. cmd. while(reader.Parameters["@count"].AppSettings["constring"]).GetString(0). } reader.Open().Add( param ).{1}". reader.VarChar). SqlDbType.Direction = ParameterDirection. cmd. con).Close(). " + "SELECT @count = COUNT(*) FROM Customers WHERE Country = @country".Parameters["@count"].Output. .Close().Read()) { Console.Parameters. con. SqlDataReader reader = cmd.{1}". SqlCommand cmd = new SqlCommand("SELECT * FROM Customers WHERE Country=@country". con.Open(). reader. param. De retinut faptul c˘ numele parametrului se prefixeaz˘ cu s ¸ a a caracterul “@”. SqlParameter param = new SqlParameter("@country".ExecuteReader(). cmd. reader.NET ConfigurationSettings.GetString(0). ˆ cazul ˆ care un parametru este de ie¸ire.Read()) { Console. SqlDbType.con).

performantele a ¸ bune. IsClosed . este de tip read-only. FieldCount . orice reˆ ıntoarcere presupune reluarea ˆ ınregistr˘rilor a (dac˘ programatorul nu implementeaz˘ el singur un mecanism de coad˘) a a a Avantajele utiliz˘rii acestui tip de obiecte sunt: accesul conectat. dac˘ se dore¸te modificarea datelor se poate folosi a s un DataSet + DataAdapter 4. OBIECTE DATAREADER con.proprietate boolean˘ read-only care spune dac˘ readerul a a contine cel putin o ˆ ¸ ¸ ınregistrare 3.metoda de modificare a pozitiei curente este ¸ doar ˆ directia ˆ ın ¸ ınainte. Caracteristicile unei asemenea clase sunt: 1.8.6.indexator care d˘ acces la cˆmpurile unei ˆ a a ınregistr˘ri a 4. se lucreaz˘ conectat la sursa de date .proprietate read-only. s a 8. implicit un parametru este de intrare ¸ • parametrii de ie¸ire sunt accesibili doar dup˘ ˆ s a ınchiderea obiectului de tip DataReader 8. consumul mic de resurse ¸i tipizarea puternic˘.6 Obiecte DataReader Un obiect de tip DataReader este folosit pentru a citi date dintr-o surs˘ a de date. HasRows . implementeaz˘ ˆ a ıntotdeauna interfata IDataReader ¸ 2. Item .d˘ num˘rul de cˆmpuri din ˆ a a a ınregistrarea curent˘ a . Remarc˘m urm˘toarele: a a • este posibil ca ˆ ıntr–o comand˘ s˘ se execute mai multe interog˘ri a a a 187 • pentru parametrul de ie¸ire numit “@count” trebuie f˘cut˘ declarare s a a de directie. returneaz˘ true daca obiectul este a deschis.6. este de tip forward-only .pe toat˘ perioada cˆt este accesat a a a un DataReader necesit˘ conexiune activ˘ a a 3. false altfel 2.1 Propriet˘¸i at 1.Close().

6.2 Metode 1.determin˘ trecerea la urm˘torul rezultat.returneaz˘ true dac˘ ˆ cˆmpul specificat prin index este a a ın a o valoare de NULL (din baza de date) 7. GetChars() . 2.6.returneaz˘ tipul coloanei specificat prin indice a 5. GetBytes(). GetChar().ˆ ınchide obiectul de citire ¸i elibereaz˘ resursele client. a 8. prime¸te a a a s ca parametri indicele de coloan˘ (int). GetDateTime().determin˘ trecerea la urm˘toarea ˆ a a ınregistrare. GetInt64(). a Preiau ca parametru indicele coloanei a c˘rei valoare se cere. folosind apelul ExecuteReader() (a se vedea sectiunea 8.3 Crearea ¸i utilizarea unui DataReader s Nu este posibil s˘ se creeze un obiect de tip DataReader cu ajutorul a unui constructor. num˘rul de octeti/caractere ce urmeaz˘ a ¸ a a fi cititi. ADO. altfel false (este posibil ca ˆ a ın a ıntr– un DataReader s˘ vin˘ mai multe rezultate. GetBoolean(). 3. GetInt32().188 CURS 8. GetInt16().returneaz˘ numele coloanei a 6. ci prin intermediul unui obiect de tip Command. IsDBNull() . pozitia ˆ buffer de ın ¸ ın la care se depun datele citite. Pentru comanda re¸ spectiv˘ se specific˘ instructiunea care determin˘ returnarea setului de date a a ¸ a precum ¸i obiectul de conexiune.returneaz˘ num˘rul de octeti / caractere cititi a a ¸ ¸ dintr–un cˆmp ce stocheaz˘ o structur˘ de dimensiuni mari. Metoda trebuie chemat˘ cel putin a ın a a ¸ o dat˘. Aceast˘ conexiune trebuie s˘ fie deschis˘ s a a a ˆ ınaintea apelului ExecuteReader(). Close() . Este s a obligatoriu apelul acestei metode ˆ inaintea ˆ ınchiderii conexiunii. dac˘ aceasta exa ista˘. ˆ acest caz returneaz˘ true. GetDataTypeName() . ¸ 4.2). pentru celelalte tipul retura nat este descris de numele metodelor. vectorul ˆ care se face citirea.NET 8. Read() . GetValue(). deoarece initial pozitia curent˘ este ˆ a ¸ ¸ a ınaintea primei ˆ ınregistr˘ri. provenind din interog˘ri a a a diferite) 8. Trecerea la urm˘toarea ˆ a ınregistrare se . Geta Value() returneaz˘ un obiect de tip Object. pozitia din acea coloan˘ de unde a ¸ a se va ˆ ıncepe citirea. GetByte(). GetFloat().3. GetName() . GetDecimal(). ˆ acest caz ea returneaz˘ true. GetDouble(). NextResult() . dac˘ aceasta a a a exist˘. GetString() returneaz˘ valorile cˆmpurilor din ˆ a a ınergistrarea curent˘.

ExecuteReader ( ). Dup˘ ce se ˆ a ¸ a ınchide acest DataReader este necesar˘ ¸i ˆ chiderea explicit˘ a conexiunii (acest lucru nu a s ın a mai e mandatoriu doar dac˘ la apelul metodei ExecuteReader s–a specificat a CommandBehavior. pozitia curent˘ la deschidere este ˆ ¸ a ınaintea primei ˆ ınregistr˘ri. object date = reader["OrderDate"]. conn.8.AppSettings["constring"]).Close (). ˆ felul acesta conexiunea se las˘ liber˘ pentru a putea fi reutilizat˘. conn. Cˆnd se dore¸te ˆ a s ıncetarea lucrului se ˆ ınchide reader–ul ¸i conexiunea. object freight = reader["Freight"]. Console. Exemplu: SqlConnection conn = new SqlConnection ( ConfigurationSettings. a Urm˘toarele observatii trebuie luate ˆ considerare atunci cˆnd se lua ¸ ın a creaz˘ cu un obiect DataReader : a • Metoda Read() trebuie s˘ fie ˆ a ıntotdeauna apelat˘ ˆ a ınaintea oric˘rui acces a la date.6.Open (). id.WriteLine ( "{0}\t{1}\t\t{2}". date. OBIECTE DATAREADER 189 face folosind metoda Read(). Dac˘ se ˆ a ıncearc˘ refolosirea conexia unii f˘r˘ ca readerul s˘ fi fost ˆ aa a ınchis se va arunca o exceptie InvalidOpera¸ tionException. freight ). SqlCommand selectCommand = new SqlCommand("select * from ORDERS". OleDbDataReader reader = selectCommand.CloseConnection). while ( reader. conn). ın a a a . ˆ caz contrar conexiunea nu poate fi a a ın reutilizat˘ a • Procesarea datelor citite trebuie s˘ se fac˘ dup˘ ˆ a a a ınchiderea conexiunii. Omiterea ˆ s ınchiderii obiectului de tip reader va duce la imposibilitatea reutiliz˘rii conexiunii initiale.Read () ) { object id = reader["OrderID"].Close (). a • ˆ Intotdeauna apelati metoda Close() pe un DataReader ¸i pe conexiunea ¸ s asociat˘ cˆt mai repede posibil. } reader. Este perfect posibil ca un obiect de tip DataReader s˘ aduc˘ datele prin a a apelul unei proceduri stocate (de fapt invocarea acestei proceduri este f˘cut˘ a a de c˘tre obiectul de tip Command ).

} }while ( reader. SqlDataReader reader = command.5 Accesarea datelor ˆ ıntr–o manier˘ sigur˘ din punct a a de vedere a tipului S˘ consider˘m urm˘toarea secvent˘ de cod: a a a ¸a while ( reader. id.6. select * from customers". Pentru ca acest at lucru s˘ nu se ˆ ample se pot folosi metodele GetXY care returneaz˘ un tip a ıntˆ a specific de date: . ADO. Console.4 Utilizarea de seturi de date multiple Este posibil ca ˆ ıntr–un DataReader s˘ se aduc˘ mai multe seturi de date.NextResult () ). date. conn ).ExecuteReader ().WriteLine ( "{0}\t\t{1}". reader[1] ).190 CURS 8. este posibil ca valorile cˆmpurilor dintr–o ˆ a a a ınregistrare s˘ fie accesate prin intermediul numelui coloanei (sau a indicelui ei. SqlCommand command = new SqlCommand ( select. freight ).Read () ) { object id = reader["OrderID"]. object freight = reader["Freight"]. a a Acest lucru ar mic¸ora num˘rul de apeluri pentru deschiderea unei conexiuni s a la stratul de date. trebuind f˘cut˘ un downcasta a ing pentru a utiliza din plin facilit˘¸ile tipului respectiv. conn. } Dup˘ cum se observ˘.6.Read () ) { Console. reader[0].WriteLine ( "{0}\t{1}\t\t{2}".Open (). Trecerea de la un set de date la altul se face cu metoda NextResult() a obiectului de tip Reader : do { while ( reader. Dezavantajul acestei metode este c˘ tipul datelor returnate este a pierdut (fiind returnate obiecte de tip Object). 8. Obiectul care permite acest lucru este chiar cel de tip Command : string select = "select * from Categories. pornind a de la 0).NET 8. object date = reader["OrderDate"].

GetDecimal ( Freight )..GetOrdinal("OrderID"). . DateTime date = reader.8. 7)..GetDecimal ( 7 ). private int OrderDate.6. Pentru a evita folosirea unor “constante magice” ca indici de coloan˘ a (precum mai sus: 0. date.WriteLine ( "{0}\t{1}\t\t{2}". reader. freight ). id. 3.GetOrdinal("OrderDate"). . decimal freight = reader. OrderID = reader. } Avantajul secventei anterioare este c˘ dac˘ se ˆ ¸ a a ıncearc˘ aducerea valorii unui a cˆmp pentru care tipul nu este dat corect se arunc˘ o exceptie InvalidCasa a ¸ tException.Read () ) { int id = reader. private int Freight. OrderDate = reader. se poate folosi urm˘toarea strategie: indicii se a obtin folosind apel de metod˘ GetOrdinal la care se specific˘ numele coloanei ¸ a a dorite: private int OrderID... . ..GetInt32 ( 0 ).GetDateTime ( 3 ). accesul la date se face sigur din punct de verere al tipului datelor. Console. altfel spus. OBIECTE DATAREADER 191 while ( reader..GetOrdinal("Freight"). Freight = reader.

192 CURS 8. ADO.NET .

. class DemoDataSource { static void Main() { SqlConnection conn = new SqlConnection( 193 . using System. DeleteComa at mand. a a Scopul ei este s˘ permit˘ umplerea unui obiect DataSet cu date ¸i reflectarea a a s schimb˘rilor efectuate asupra acestuia ˆ a ınapoi ˆ baza de date (DataSet perın mite lucrul deconectat de la baza de date). UpdateCommand.NET (2) 9. using System.NET specific fiec˘rui tip de surs˘ de date. Command.1 Obiecte DataAdapter La fel ca ¸i Connection. ¸tergere) trebuie specificate obiecte de tip s comand˘ via propriet˘¸ile: InsertCommand. ˆ cazul ˆ care se dore¸te ¸i modificarea informatiilor din In ın s s ¸ sursa de date (inserare. Pentru orice obiect a a a de acest tip trebuie specificat˘ minim comanda de tip SELECT care care a s˘ populeze un obiect de tip DataSet. ).SqlClient. .Curs 9 ADO.Data. OleDat bCommand. modificare. Orice clas˘ de tipul DataAdapter (de ex SqlDataAdapter ¸i OleDbDataAdapter) a s este derivat˘ din clasa DbDataAdapter (clas˘ abstract˘). DataReader.Data. acest lucru este stabilit prin intera mediul propriet˘¸ii SelectCommand de tip Command (SqlCommand. using System. obiectele de tip DataAdapter s fac parte din furnizorul de date . Exemplu: mai jos se preiau ˆ ınregistr˘rile din 2 tabele: Authors ¸i TitleAua s thor ¸i se trec ˆ s ıntr–un obiect de tip DataSet pentru a fi procesate ulterior. .

. 2. strConn). au_fname. Rea a turneaz˘ de fiecare dat˘ num˘rul de ˆ a a a ınregistr˘ri care au fost aduse din a ˆ clipa ˆ care se apeleaz˘ Fill() se procedeaz˘ astfel: baz˘. SqlDataAdapter da = new SqlDataAdapter(cmd). au_lname FROM authors". title_id FROM titleauthor"."TitleAuthor").NET (2) ConfigurationSettings. conn). daTitleAuthor.". sau: String strCmd = "SELECT * FROM Employees". SqlDataAdapter daTitleAuthor = new SqlDataAdapter("SELECT au_id. SqlDataAdapter daAuthors = new SqlDataAdapter("SELECT au_id.AppSettings["constring"]).1 Metode 1. } } Prezent˘m mai jos cele mai importante componente ale unei clase de tip a DataAdapter. 9. sau: SqlCommand cmd = new SqlCommand("SELECT * FROM Employees").194 CURS 9.. Pentru un obiect de s tip SqlDataAdapter se poate crea o instant˘ ˆ urm˘toarele moduri: ¸a ın a SqlDataAdapter da = new SqlDataAdapter(). SqlDataAdapter da = new SqlDataAdapter(strCmd.1.conn). ın num˘rul de ˆ a ınregistrare cu care s˘ se ˆ a ınceap˘ popularea (prima avˆnd a a indicele 0) ¸i num˘rul de ˆ s a ınregistr˘ri care urmeaz˘ a fi aduse. Fill() – metod˘ polimorfic˘. eventual a numelui tablei din acest DataSet. In a ın a a . daAuthors. Permite specificarea obiectului DataSet ˆ care se depun datele. ADO.Fill(ds. permitˆnd umplerea unei tabele dintr–un a a ¸a obiect de tip DataSet cu date.Fill(ds."Author"). String strConn = ". Constructori de la cei impliciti pˆn˘ la cei ˆ care se specific˘ o comand˘ ¸ a a ın a a de tip SELECT ¸i conexiunea la sursa de date.

InsertCommand.2 Propriet˘¸i at 1. Pentru a functiona are nevoie de obiecte de ¸ tip comand˘ adecvate: propriet˘¸ile InsertCommand. a 9. MissingSchemaAction – de tip enumerare MissingSchemaAction. dar dac˘ aceasta a fost deschis˘ ˆ a a ınaintea metodei Fill() atunci tot programatorul trebuie s˘ o ˆ a ınchid˘. contin comenzile ce se execut˘ pentru selectarea ¸ a sau modificarea datelor ˆ sursa de date.2. permitˆnd reflectarea modific˘rilor efeca a ¸a a tuate ˆ ıntre–un DataSet. 9. a 3. Update() – metod˘ polimorfic˘. DataAdapter adaug˘ coloana la schema tablei a • AddWithKey . determin˘ ce se face atunci cˆnd datele care sunt aduse nu se potrivesc a a peste schema tablei ˆ care sunt depuse.NET. Poate avea urm˘toarele valori: ın a • Add .implicit. ceea ce duce la pierdere a de date pe DataSet • Error .ca mai sus. Marele ei a s ¸ s ¸ . SelectCommand. UpdateCommand – de tip Command.9.se genereaz˘ o exceptie de tipul InvalidOperationExcepa ¸ tion.2 Clasa DataSet Clasa DataSet nu mai face parte din biblioteca unui furnizor de date ADO. DeleteCommand. dar adaug˘ ¸i informatii relativ la cine as ¸ este cheia primar˘ a • Ignore . CLASA DATASET (a) Se deschide conexiunea (dac˘ ea nu a fost explicit deschis˘) a a 195 (b) Se aduc datele ¸i se populeaz˘ un obiect de tip DataTable din s a DataSet (c) Se ˆ ınchide conexiunea (dac˘ ea nu a fost explicit deschis˘!) a a De remarcat c˘ un DataAdapter ˆsi poate deschide ¸i ˆ a ı¸ s ınchide singur conexiunea. pentru a se putea a a face popularea setului de date. Ea poate s˘ contin˘ reprezent˘ri tabelare ale a ¸ a a datelor din baz˘ precum ¸i diferite restrictii ¸i relatii existente.se ignor˘ lipsa coloanei respective. 2. M˘car proprietatea Selectın a Command trebuie s˘ indice c˘tre un obiect valid. fiind standard. Returneaz˘ s a a a de fiecare dat˘ num˘rul de ˆ a a ınregistr˘ri afectate. DeleteCommand a at ¸i UpdateCommand trebuie s˘ indice c˘tre comenzi valide.1.

2. procesarea datelor desf˘¸urˆndu–se independent ¸ as a de ea. a ¸ s 2.2 Clasa DataTable Datele sunt continute ˆ ¸ ıntr-un DataSet sub forma unor tabele de tip DataTable.1 contine o vedere partial˘ asupra clasei DataSet.2. a a 3. ¸ ¸ at 9. cˆt ¸i ˆ interiorul unui a a s ın . eliminˆnd a a ˆ felul acesta.196 CURS 9. Fiecare ¸ ¸ DataTable este compus˘ dintr-o colectie de linii ¸i coloane. Colectia Tables contine 0 sau mai multe obiecte DataTable.1: Structura unui DataSet 9. ¸ ¸ folosite pentru marcarea leg˘turilor p˘rinte–copil. Figura 9. ADO. Colectia ExtendedProperties contine propriet˘¸i definite de utilizator.1 Continut ¸ Prezent˘m succint continutul unui DataSet: a ¸ 1.NET (2) avantaj este faptul c˘ permite lucrul deconectat de la sursa de date. ¸ ¸ a Figura 9. Colectia Relations contine 0 sau mai multe obiecte de tip DataRelation. Aceste obiecte pot fi folosite atˆt independent. In un server de aplicatii sau un client oarecare poate apela la serverul de baze ¸ de date doar cˆnd preia datele sau cˆnd se dore¸te salvarea lor. Remarcabil este faptul c˘ un DataSet poate face s a abstractie de sursa de date. Functioneaz˘ a a s ¸ a ˆ strˆns˘ leg˘tur˘ cu clasa DataAdapter care actioneaz˘ ca o punte ˆ ın a a a a ¸ a ıntre un DataSet ¸i sursa de date. necesitatea unei conexiuni permanente precum la DataReader.

Add(tempRow). CLASA DATASET 197 DataSet ca elemente ale colectiei Tables. Rows de linii ¸i Constraints de constrˆngeri. idColumn. tempRow = myTable. Constrˆngeri a Constrˆngerile sunt folosite pentru a descrie anumite restrictii aplicate a ¸ asupra valorilor din coloane. Toate obiectele de constrˆngere se afl˘ ˆ s a a a a ın colectia Constraints a unei tabele. Exemplu: DataColumn myColumn = new DataColumn("title".GetType("System. idColumn.String")). Pentru crearea unei linii se poate apela metoda ¸ a NewRow pentru o tabel˘ a c˘rei schem˘ se cunoa¸te.ReadOnly = true. myTable.NewRow(). tempRow["Name"] = "Book". idColumn. tempRow["Category"] = 1.NET exist˘ dou˘ tipuri de constrˆngeri: In a a a de unicitate ¸i de cheie str˘in˘. ¸ .GetType("System. Type.Columns.9. tempRow["ID"] = 1. Definirea unei coloane ca fiind de tip autonumber (ˆ vederea stabilirii ei ın ca ¸i cheie pe o tabel˘) se face astfel: s a DataColumn idColumn = new DataColumn("ID".Int32")). ˆ ADO. a Orice obiect DataTable contine o proprietate Rows ce da acces la colectia de ¸ ¸ obiecte DataRow continut˘.AutoIncrement = true.2. s a DataColumn Un obiect DataColumn define¸te numele ¸i tipul unei coloane care face s s parte sau se adaug˘ unui obiect DataTable.Add. Un DataTable contine o colectie ¸ ¸ ¸ Columns de coloane.Rows. Type. Un obiect de acest tip se obtine a ¸ prin apel de constructor sau pe baza metodei DataTable. Mai jos este dat˘ a a a s a secventa de cod care creeaz˘ o linie nou˘ pentru o tabel˘ ¸i o adaug˘ acestesia: ¸ a a as a DataRow tempRow.AutoIncrementSeed = 1. DataRow Un obiect de tip DataRow reprezint˘ o linie dintr-un obiect DataTable.

myTable. custOrderFK.specific˘ actiunea care se va efectua atunci a ¸ cˆnd se ¸terge sau modific˘ valoarea dintr–o anumit˘ coloan˘. De exa s a a a emplu se poate decide c˘ dac˘ se sterge o ˆ a a ınregistrare dintr-o tabel˘ a atunci s˘ se ¸tearg˘ ¸i ˆ a s a s ınregistr˘rile copil.UpdateRule: s – Rule.Tables["CustTable"]. pk[0] = myTable. Restrictia s ¸ se adaug˘ la tabla copil.precizeaz˘ c˘ ˆ a a ıntr-o anumit˘ coloan˘ valorile sunt a a ˆ unice. .actiunea implicit˘. at DataColumn[] pk = new DataColumn[1].Tables["OrdersTable"].Columns["CustomerID"]).198 CURS 9. ¸terge sau modific˘ ˆ ¸ a s a ınregistr˘rile a afectate – Rule. care fac parte dintr-un DataSet).Tables["OrdersTable"].DeleteRule ¸i ForeignKeyConstraint. custDS.DeleteRule = Rule. ADO.None.SetDefault . Incercarea de a seta valori duplicate pe o coloana pentru care s-a precizat restrictia duce la aruncarea unei exceptii. //Nu se poate sterge un client care are comenzi facute custDS.SetNull . Valorile care se pot seta a pentru o asemenea constrˆngere se specific˘ ˆ propriet˘¸ile ForeignKa a ın at eyConstraint. Mai sus s-a declarat o relatie de tip cheie str˘in˘ ˆ ¸ a a ıntre dou˘ tabele a (“CustTable” ¸i “OrdersTable”.Columns["ID"].Add(custOrderFK).custDS. Este necesar˘ ¸ ¸ a o asemenea coloan˘ ˆ clipa ˆ care se folose¸te metoda Find pentru a ın ın s proprietatea Rows: ˆ acest caz trebuie s˘ se specifice o coloan˘ pe care ın a a avem unicitate.se seteaz˘ valoare de null pentru ˆ a ınregistr˘rile afeca tate – Rule.Columns["CustomerID"].Constraints.nu se execut˘ nimic a Exemplu: ForeignKeyConstraint custOrderFK=new ForeignKeyConstraint ("CustOrderFK".Cascade .None .PrimaryKey = pk. a Stabilirea cheii primare O cheie primar˘ se define¸te ca un vector de coloane care se atribuie a s propriet˘¸ii PrimaryKey a unei tabele (obiect DataTable). • ForeignKeyConstraint .NET (2) • UniqueConstraint .se seteaz˘ valoarea implicit˘ definit˘ ˆ baz˘ a a a ın a pentru cˆmpul respectiv a – Rule.

O dat˘ obtinut un asemenea obiect a ¸ (care contine cel putin o comand˘ de tiop SELECT ) se poate apela metoda ¸ ¸ a Fill() care prime¸te ca parametru DataSet-ul care se umple ¸i optional numele s s ¸ tabelei care va contine datele: ¸ //defineste comanda de selectare din baza de date String mySqlStmt ="SELECT * FROM Customers".4 Popularea unui DataSet De¸i un obiect DataSet se poate popula prin crearea dinamic˘ a obiectelor s a DataTable. SqlCommand myCommand = new SqlCommand(mySqlStmt.Relations. //Construieste obiectele de conexiune + comanda SELECT SqlConnection myConnection = new SqlConnection(myConString).Relations.3 Relatii ˆ ¸ ıntre tabele Proprietatea Relations a unui obiect de tip DataSet contine o colectie de ¸ ¸ obiecte de tip DataRelation folosite pentru a figura relatiile de tip p˘rinte– ¸ a copil ˆ ıntre dou˘ tabele. //sau myDataSet. de exemplu sub forma: ¸ a myDataSet. cazul cel mai des ˆ alnit este acela ˆ care se populeaz˘ prin ıntˆ ın a intermediul unui obiect DataAdapter. if ( line != null ) //proceseaza linia 9.9. //Construieste obiectul DataAdapter . 9.//cheia dupa care se face cautarea DataRow line = myTable. myDataSet. DataColumn).Tables["Customers"]. DataColumn[]).Relations. Aceste relatii se precizeaz˘ ˆ esent˘ ca niste perechi a ¸ a ın ¸a de array-uri de coloane sau chiar coloane simple din cele dou˘ tabele care se a relationeaz˘. concret: myDataSet.Add(DataColumn. CLASA DATASET 199 Proprietatea Rows a clasei DataTable permite c˘utarea unei anumite linii a din colectia continut˘ dac˘ se specific˘ un obiect sau un array de obiecte ¸ ¸ a a a folosite pe post de cheie: object key = 17. String myConString = ConfigurationSettings. myConnection).2.Rows.2.Find(key).Columns["CustomerID"]).Add( myDataSet.Tables["Orders"].2.AppSettings["constring"].Add(DataColumn[].Columns["CustomerID"].

5 Propagarea modific˘rilor c˘tre baza de date a a Pentru a propaga modific˘rile efectuate asupra continutului tabelelor a ¸ dintr-un DataSet c˘tre baza de date este nevoie s˘ se defineasc˘ adecvat a a a obiecte comand˘ de tip INSERT. Fiecare linie modificat˘ din colectia Rows a unei tabele va avea moda ¸ ificat˘ valoarea propriet˘¸ii RowState astfel: DataRowState. //construieste obiectul DataSet si il umple cu date DataSet myDataSet = new DataSet(). "Customers"). UPDATE. Pentru cazuri sima ple se poate folosi clasa SqlCommandBuilder care va construi singur˘ aceste a comenzi. iar pentru obiectul DataAdapter care as face aducerea din baz˘ se seteaz˘ proprietatea MissingSchemaAction pe vala a oarea MissingSchemaAction. ADO. Acela¸i DataSet se a s poate popula ˆ continuare cu alte tabele pe baza aceluia¸i sau a altor obiecte ın s DataAdapter. numit ”Customers”. Trebuie specificat˘ cel putin cheia primar˘ sau o coloan˘ cu constrˆngere a ¸ a a a de unicitate ˆ comanda SELECT. myDataAdapter.NET (2) SqlDataAdapter myDataAdapter = new SqlDataAdapter(). Trebuie specificat˘ o comand˘ de tip SELECT care s˘ aduc˘ datele a a a a dintr-o singur˘ tabel˘ a a 2.AddWithKey (implicit este doar Add ). ın Pentru cea de a doua conditie se poate proceda ˆ felul urm˘tor: ˆ comanda ¸ ın a ın SELECT se specific˘ ¸i aducerea cheii.200 CURS 9. 9. Datele aduse mai sus sunt depuse ˆ ıntr-un obiect de tip DataTable din interiorul lui DataSet.Added pentru a at . E nevoie s˘ se satisfac˘ 2 conditii ın ¸ a a ¸ atunci cˆnd se uzeaz˘ de un astfel de obiect: a a 1. //seteaza proprietatea SelectCommand pentru DataAdapter myDataAdapter.Fill(myDataSet.SelectCommand = myCommand. Accesul la acest tabel se face prin constructia ¸ myDataSet.Tables["Customers"] sau folosind indici ˆ ıntregi (prima tabel˘ are indicele 0).2. DELETE. Clasa CommandBuilder Un obiect de tip CommandBuilder (ce provine din furnizorul de date) va analiza comanda SELECT care a adus datele ˆ DataSet ¸i va construi cele ın s 3 comenzi de update ˆ functie de aceasta.

printr-un join) se pot specifica propriile comenzi SQL prin intermediul propriet˘¸ilor InsertCommand.9. UpdateCommand ale at dataAdapter-ului. ¸tergerea de ˆ a s ınregistr˘ri din baza de date. Comanda de Update se d˘ doar pentru acest set de modific˘ri. name. Pentru fiecare linie dintr-o tabel˘ care este modificat˘/ad˘ugat˘/¸tears˘ se va apela coa a a a s a manda SQL corespunz˘toare. a a reducˆnd astfel traficul spre serverul de baze de date. //accepta schimbarile din dataset ds.conn).Fill(ds). modificarea.AppSettings["constring"]).Deleted dac˘ e ¸tears˘ ¸i DataRowa a a a s a s State. //determina liniile care au fost schimbate DataSet dsChanges = ds.2.Modified dac˘ a fost modificat˘. at DeleteCommand UpdateCommand ale obiectului DataAdapter. ¸ Ar˘t˘m mai jos modul de utilizare a clasei SqlCommandBuilder pentru aa ad˘ugarea. CLASA DATASET 201 o linie nou˘ ad˘ugat˘.Aceste comenzi pot fi fraze SQL parametrizate a sau pot denumi proceduri stocate aflate ˆ baz˘. Se determin˘ apoi liniile care au fost modificate (prin a interogarea st˘rii lor) ¸i se obtine un nou DataSet care le va contine doar a s ¸ ¸ pe acestea. a SqlConnection conn = new SqlConnection( ConfigurationSettings. DeleteCommand.AcceptChanges(). Apelul de update pe un dataReader a a va apela comanda necesar˘ pentru fiecare linie care a fost modificat˘.Update(dsChanges). da. ˆ a a ın functie de starea ei. ın a S˘ presupunem c˘ s-a definit un DataAdapter legat la o baz˘ de date. a Update folosind comenzi SQL Atunci cˆnd interog˘rile de aducere a datelor sunt mai complexe (de a a exemplu datele sunt aduse din mai multe table. a a a Instructiunea de selectie este ¸ ¸ . da = new SqlDataAdapter("SELECT id. address FROM customers". DataRowState.GetChanges(). if (dsChanges != null) { // modifica baza de date da. SqlCommandBuilder cb = new SqlCommandBuilder(da). } ˆ clipa ˆ care se creeaz˘ obiectul SqlCommandBuilder automat se vor comIn ın a pleta propriet˘¸ile InsertCommand.

Address. fie deloc. Country. Address = @Address.CommandText = @"INSERT INTO Customers ( CompanyName. scade suma din primul cont 2. Address. 9.202 CURS 9.InsertCommand. Address. deoarece (ˆ acest caz) ea este de tip AutoNumber (SGBD-ul este cel care face manageın mentul valorilor acestor cˆmpuri. @Country). Country = @Country WHERE (CustomerID = @ID)". @@Identity reprezint˘ a a id-ul noii ˆ ınergistr˘ri ad˘ugate ˆ tabel˘. Update-ul efectiv se face prin prima instructiune de tip Update.UpdateCommand. CustomerID FROM Customers unde CustomerID este cheia. CustomerID FROM Customers WHERE (CustomerID = @@Identity)". Ultima instructiune va duce la a a ın a ¸ reactualizarea obiectului DataSet. Country) VALUES (@CompanyName. @Address. de exemplu prin alegerea lor s dintr-un tabel. Pentru modificarea continutului unei linii se poate declara instructiunea ¸ ¸ de UPDATE astfel: da. pentru ca acesta s˘ contin˘ modificarea a ¸ a efectuat˘ (de exemplu ar putea aduce valorile implicite puse pe anumite a coloane). nu programatorul). Pentru inserarea unei noi ˆ ınregistr˘ri s–ar putea a scrie codul de mai jos: //da=obiect DataAdapter da. ADO.3 Tranzactii ˆ ADO.NET ¸ ın O tranzactie este un set de operatii care se efectueaz˘ fie ˆ ˆ ¸ ¸ a ın ıntregime.NET (2) SELECT CompanyName. Valoarea pentru cheia CustomerID nu s-a specificat. adaug˘ suma la al doilea cont a Ar fi inadmisibil ca primul pas s˘ reu¸easc˘ iar al doilea s˘ e¸ueze. Operatia presupune 2 pa¸i: ın ¸ s 1. Valorile ¸ pentru ace¸ti parametri se vor da la runtime. Country. Comanda de update este ca la cazul precedent. Tranzactiile a s a a s ¸ satisfac ni¸te propriet˘¸i strˆnse sub numele ACID: s at a .CommandText = @"UPDATE Customers SET CompanyName = @CompanyName. SELECT CompanyName. S˘ presupunem c˘ se dore¸te trecerea unei anumite sume de bani a a s dintr-un cont ˆ altul.

myConnection.Open().NET acest lucru s-ar face astfel: SqlConnection myConnection = new SqlConnection(myConnString). myTrans = myConnection. altfel efectueaz˘ ROLLBACK a a 5.CreateCommand().NET este: ¸ 1. deschide conexiunea la baza de date 2. dac˘ tranzactia se poate efectua (nu sunt exceptii sau anumite conditii a ¸ ¸ ¸ sunt ˆ ındeplinite). Sunt trei comenzi care se folosesc ˆ context de tranzactii: ın ¸ • BEGIN .BeginTransaction().schimb˘rile care apar ˆ tipul tranzactiei sunt permaa ın ¸ nent stocate pe un mediu. atunci toate operatiile a ¸ s a ¸ efectuate de la ˆ ınceputul tranzactiei vor fi neglijate ¸ Schema de lucru cu tranzactiile sub ADO. efectueaz˘ COMMIT. //Trebuie asignate ambele obiecte: conexiune si tranzactie .toate operatiile din tranzactie ar trebui s˘ aib˘ succes ¸ ¸ a a sau s˘ e¸ueze ˆ a s ımpreun˘ a • consistent˘ .9.ˆ ınainte de executarea unei comenzi SQL sub o tranzactie. SqlCommand myCommand1 = myConnection. SqlCommand myCommand2 = myConnection.dac˘ o parte a tranzactiei e¸ueaz˘. SqlTransaction myTrans.3.nici o tranzactie nu ar trebui s˘ afecteze o alta care ruleaz˘ ¸ a a ˆ acela¸i timp ın s • durabilitate .CreateCommand().se spune c˘ o tranzactie este terminat˘ cˆnd toate schimb˘rile a ¸ a a a cerute sunt trecute ˆ baza de date ın • ROLLBACK .tranzactia duce baza de date dintr-o stare stabil˘ ˆ alta ¸a ¸ a ın • izolare . ˆ ıncepe tranzactia ¸ 3.NET ¸ IN 203 • atomicitate . TRANZACTII ˆ ADO. ˆ ınchide conexiunea la baza de date Sub ADO. execut˘ comenzi pentru tranzactie a ¸ 4. ¸ aceasta trebuie s˘ fie initializat˘ a ¸ a • COMMIT .

} Comanda de ROLLBACK se poate executa ¸i ˆ alte situatii.Close(). a as s . RegionDescription) VALUES (100.WriteLine("Ambele inregistrari au fost scrise. } finally { myConnection. } catch(Exception e) { myTrans.Transaction = myTrans.Commit(). ADO.ExecuteNonQuery(). myCommand2.Transaction = myTrans. RegionDescription) VALUES (101.Rollback(). ’Description’)". myCommand2.204 CURS 9."). myCommand2. ’Description’)".NET (2) //unui obiect de tip comanda care va participa la tranzactie myCommand1. myTrans. myCommand1.ExecuteNonQuery(). de exemplul s ın ¸ comanda efectuat˘ dep˘¸te¸te stocul disponibil. Console.CommandText = "Insert into Region (RegionID. try { myCommand1.CommandText = "Insert into Region (RegionID.

¸ a ¸ altele care s˘ r˘spund˘ actiunilor utilizatorului). Pentru ca o interfat˘ utilizator s˘ poat˘ fi folosit˘ f˘r˘ ¸ ¸a a a a aa a se a¸tepta ˆ s ıncheierea unei anumite secvente de instructiuni. ˆ BCL este definit tipul delegat ThreadStart. exprimarea procesului de calcul se poate face foarte natural sub form˘ de fire de exectie. al c˘rei constructor preia un singur argument de tip delea gat. ˆ a a ¸ ın cadrul unei aplicatii. Vom discuta ˆ a ın ¸ ın cele ce urmeaz˘ despre managementul thread–urilor ¸i despre sincronizare.1 10. a s De cele mai multe ori crearea de thread–uri este necesar˘ pentru a da a utilizatorului impresia c˘ programul execut˘ mai multe actiuni simultan. vom folosi alternativ termenii “thread” ¸i “fir de executie” s ¸ 205 . Crearea unui fir de executie se face pe baza unei metode care returneaz˘ ¸ a void ¸i nu preia nici un parametru: s 1 Engl: threads.Curs 10 Fire de executie ¸ Firele de executie1 sunt responsabile cu multitasking–ul ˆ interiorul unei ¸ ın aplicatii.1 Managementul thread–urilor Pornirea thread–urilor Cea mai simpl˘ metod˘ de a crea un fir de exectie este de a crea o instant˘ a a ¸ ¸a a clasei Thread. care este folosit ca proIn totip pentru orice metod˘ care se vrea a fi lansat˘ ˆ a a ıntr–un fir de executie.1.Threading. ¸ Declaratia de ThreadStart este: ¸ public delegate void ThreadStart(). Pentru probleme de calcul a a a ¸ numeric. e nevoie de ¸ ¸ mai multe fire de executie (unele pentru procesarea efectiv˘ a informatiei. Clasele ¸i interfetele responsabile pentru crearea aplicatiilor mul¸ s ¸ ¸ tithreading se g˘sesc ˆ spatiul de nume System. a ¸ 10.

Dup˘ t. Un exemplu simplu este: using System.Start() poate s˘ a ¸ a a apar˘ ˆ a ınainte sau dup˘ mesajul tip˘rit de metoda WorkerThreadMethod(). class SimpleThreadApp { public static void WorkerThreadMethod() { Console. Console. class Tester . mesajul de dup˘ t. } public static void Main() { ThreadStart worker = new ThreadStart(WorkerThreadMethod). Exemplul urm˘tor porne¸te dou˘ fire de executie.Threading.WriteLine("[Main] Creating worker thread"). a a De remarcat c˘ simpla creere a firului de executie nu determin˘ ¸i pornirea a ¸ as lui: acest lucru se ˆ ampl˘ dupa apelul metodei Start definit˘ ˆ clasa ıntˆ a a ın Thread. Console.WriteLine( "[Main] Have requested the start of worker thread"). Functiile care contin a s a ¸ ¸ ¸ codul ce se va executa ˆ cˆte un thread sunt Increment() ¸i Decrement(): ın a s using System.WriteLine("[WorkerThreadMethod] Worker " + "thread started"). Mesajul din a s Main va fi tip˘rit ˆ a ınaintea celui din thread–ul t. ˆ functie de cum anume ın ¸ se planific˘ thread–urile pentru executie.ReadLine(). Thread t = new Thread(worker).Start() exist˘ un singur thread: cel dat de pornirea metodei a a a Main. using System. } } Pˆn˘ la linia t. Console.Start() sunt 2 thread–uri: cel anterior ¸i t. Thread myThread = new Thread( ts ). using System.Start(). FIRE DE EXECUTIE ¸ ThreadStart ts = new ThreadStart(MyFunc).206 CURS 10.Threading. t.

.i<=1000. i). i). } 207 Incrementer ThreadStart(Incrementer) ).i--) { Console.WriteLine( "Incrementer: {0}".DoTest( ). MANAGEMENTUL THREAD–URILOR { static void Main( ) { Tester t = new Tester( ). t2. Incrementer: Incrementer: Incrementer: Incrementer: 102 103 104 105 .i++) { Console. public void Incrementer( ) { for (int i = 1. Decrementer ThreadStart(Decrementer) ).i>0. } } } La ie¸ire se vor mixa mesajele tip˘rite de primul thread cu cele tip˘rite s a a de cel de–al doilea thread: . } public void DoTest( ) { // creeaza un thread pentru Thread t1 = new Thread( new // creeaza un thread pentru Thread t2 = new Thread( new // porneste threadurile t1.. t.Start( ).Start( ).10. } } public void Decrementer( ) { for (int i = 1000.1.WriteLine("Decrementer: {0}".

106 1000 999 998 997 CURS 10. a ın s Dac˘ de exemplu ˆ metoda Main se lanseaz˘ o colectie de thread–uri a ın a ¸ (stocat˘ ˆ myThreads). acest lucru se va face folosind apelul a ¸ t. atunci pentru a se continua executia numai dup˘ ce a ın ¸ a toate firele din colectie s–au terminat. ˆ acest moment firul de executie care ¸ ın a ın ¸ a apelat t.CurrentThread. } Console. 10. etc.Join().Join() ˆ ınaintea instructiunii ˆ cauz˘.WriteLine(‘‘All my threads are done’’). FIRE DE EXECUTIE ¸ Perioada de timp alocat˘ fiec˘rui thread este determinatu˘ de c˘tre plania a a a ficatorul de fire de executie2 ¸i depinde de factori precum viteza procesorului. i se seteaz˘ numele (proprietate de tip read/write) ¸i se afi¸eaz˘ pe a s s a ecran: Thread current = Thread. Console.WriteLine("nume={0}".Name = "My name". ˆ a ¸ ın ınaintea unei instructiuni trebuie s˘ se asigure fap¸ a tul c˘ un alt fir de executie t s-a terminat.208 Incrementer: Decrementer: Decrementer: Decrementer: Decrementer: . Mesajul final se va tip˘ri doar cˆnd toate firele de executie s–au terminat. se procedeaz˘ astfel: ¸ a foreach( Thread myThread in myThreads ) { myThread.2 Metoda Join() Exist˘ situatii ˆ care.1.Name )..CurrentThread pentru firul de executie curent. ¸ s gradul lui de ocupare. ˆ ¸ In exemplul de mai jos se obtine obiectul Thread asociat firului de executie ¸ ¸ curent.. a a ¸ 2 Engl: thread scheduler .Join() intr˘ ˆ a¸teptare. O alt˘ modalitate de obtinere a unei referinte la un thread este prin apelul a ¸ ¸ metodei statice Thread. current. current.

3 Suspendarea firelor de executie ¸ Se poate ca ˆ anumite cazuri s˘ se doreasc˘ suspendarea unui fir de ın a a executie pentru o scurt˘ perioad˘ de timp.1.Sleep(1000). ˆ acest fel se semnaleaz˘ planificatorului de fire de executie c˘ poate In a ¸ a lansa un alt thread. care reprezint˘ cea mai mic˘ unitate de timp a a care poate fi specificat˘. atunci ie¸irea se schimb˘ dramatic: s a Iesire (extras) Incrementer: 0 Incrementer: 1 Decrementer: 1000 Incrementer: 2 Decrementer: 999 Incrementer: 3 Decrementer: 998 Incrementer: 4 Decrementer: 997 Incrementer: 5 Decrementer: 996 Incrementer: 6 Decrementer: 995 10. pe care ¸ a firul respectiv o poate prinde ¸i procesa. egal˘ cu 100 nanosecunde.1.10. iar a doua variant˘ preia un ara a gument de tip TimeSpan. permitˆndu–i eliberarea de resurse s ¸a alocate. se recomand˘ ca o metod˘ care se va lansa ca fir de a a . un fir de executie moare dup˘ ce se termin˘ de executat.4 Omorˆrea thread–urilor a De obicei. MANAGEMENTUL THREAD–URILOR 209 10. Se ¸ a a poate totu¸i cere unui fir de executie s˘ ˆsi ˆ s ¸ a ı¸ ınceteze executia folosind metoda ¸ Abort(). Acest lucru va duce la aruncarea unei exceptii ˆ interiorul firului ¸ ın de executie c˘ruia i se cere suspendarea: ThreadAbortedException.Sleep(1) dup˘ a ın a a fiecare WriteLine(). care poate prelua un parametru de tip int a ınc˘ a reprezentˆnd milisecundele de “adormire”. Pentru a cere firului a a de executie curent s˘ se suspende pentru o secund˘. Ca atare. se execut˘ ˆ cadrul ¸ a a a ın acestuia: Thread. Clasa Thread ofer˘ o metod˘ ¸ a a a a static˘ supraˆ arcat˘ Sleep(). Dac˘ ˆ exemplul de mai sus se adaug˘ un apel Thread.1.

IsBackground=true.WriteLine("Started thread {0}". ¸ a a ¸ ¸ dup˘ care un bloc catch ¸i/sau finally care vor efectua eliberarea de resurse. new Thread( new ThreadStart(Incrementer) ). myThread. Console.Name).Sleep(50). } // dupa ce firele se pornesc.Threading.Join( ). foreach (Thread myThread in myThreads) { myThread. // porneste fiecare thread int ctr = 1.ToString( ).Abort( ). ctr++. // asteapta ca fiecare thread sa se termine foreach (Thread myThread in myThreads) { myThread. } . using System. a s Exemplu: using System. // comanda oprirea threadului 1 myThreads[1]. myThread.Start( ). new Thread( new ThreadStart(Incrementer) ) }.Name = "Thread" + ctr.210 CURS 10.DoTest( ). class Tester { static void Main( ) { Tester t = new Tester( ). t. myThread. } public void DoTest( ) { // creeaza un vector de threaduri Thread[] myThreads = { new Thread( new ThreadStart(Decrementer) ). FIRE DE EXECUTIE ¸ executie s˘ se compun˘ dintr–un bloc try care contine instructiunile utile. Thread.

WriteLine( ‘‘Thread {0} interrupted! Cleaning up.WriteLine("All my threads are done. Thread.Sleep(1)..i<=1000.CurrentThread.WriteLine(‘‘Thread {0}. ’’."). } } // numara cresacator pana la 1000 public void Incrementer( ) { try { for (int i =1..WriteLine(‘‘Thread {0} Exiting. } } catch (ThreadAbortedException) { Console.i>0. .Name).. Thread.Name). i). } finally { Console. Thread. Incrementer: {1}’’.WriteLine(‘‘Thread {0}.’’.CurrentThread.i++) { Console.Name. i). 211 } // numara descrescator de la 1000 public void Decrementer( ) { try { for (int i = 1000.’’. Thread. Thread.10.Name.CurrentThread. Thread.1.i--) { Console. Decrementer: {1}’’.Sleep(1)..WriteLine( ‘‘Thread {0} interrupted! Cleaning up. MANAGEMENTUL THREAD–URILOR Console. } } catch (ThreadAbortedException) { Console.CurrentThread.

Thread Thread2 Exiting. Incrementer: 3 Started thread Thread3 Thread Thread1. Incrementer: 0 Thread Thread1. Incrementer: 7 Thread Thread1. Decrementer: 998 Started thread Thread2 Thread Thread1. Incrementer: 2 Thread Thread1. Decrementer: 1000 Thread Thread1. Thread. Decrementer: 997 Thread Thread2. Incrementer: 3 . Decrementer: 991 Thread Thread3. FIRE DE EXECUTIE ¸ } finally { Console.CurrentThread. Decrementer: 989 Thread Thread3.212 Thread. Decrementer: 988 Thread Thread3. Incrementer: 6 Thread Thread1.. Incrementer: 0 Thread Thread2. Incrementer: 2 Thread Thread1. Incrementer: 4 Thread Thread2. Decrementer: 993 Thread Thread2. ’’. Incrementer: 5 Thread Thread1. Incrementer: 1 Thread Thread1.. Decrementer: 990 Thread Thread3.Name). Decrementer: 994 Thread Thread2.Name). } } } Ie¸ire: s Started thread Thread1 Thread Thread1. Decrementer: 996 Thread Thread2.WriteLine( ‘‘Thread {0} Exiting. CURS 10. Decrementer: 999 Thread Thread1.CurrentThread. Decrementer: 995 Thread Thread2. Decrementer: 992 Thread Thread2. Incrementer: 1 Thread Thread2 interrupted! Cleaning up. Thread Thread1.

AboveNormal.1.6 Fire ˆ fundal ¸i fire ˆ prim-plan ın s ın Relativ la proprietatea boolean˘ IsBackground. ThreadPriorityLevel. CLR va mentine a a a ¸ ın ¸ aplicatia ˆ executie.Priority = ThreadPriorityLevel. Prioritatea este descresc˘toare ˆ lista prezentat˘. Decrementer: Incrementer: Decrementer: Incrementer: 987 4 986 5 213 Thread1. ThreadPriorityLevel. ThreadPriorityLevel.Normal...TimeCritical. trebuie f˘cut˘ precizarea a a a c˘ un fir de executie poate s˘ se execute ˆ fundal (background) sau ˆ prim a ¸ a ın ın plan (foreground).5 Sugerarea priorit˘¸ilor firelor de executie at ¸ Un fir de executie se lanseaz˘ implicit cu prioritatea ThreadPriorityLevel. ThreadPriorityLevel. ¸ a Dar scheduler–ul poate fi influentat ˆ activitatea sa prin setarea de diferite ¸ ın nivele de prioritate pentru fire. Pe baza priorit˘¸ii procesului care contine firele de ın a at ¸ executie ¸i a priorit˘¸ii firelor. class Test { static void Main() .Idle. se calculeaz˘ un nivel de propritate (de ex. Setarea unei anumite priorit˘¸i se face folosind proprietatea Priority: at myThread. Decrementer: 1 Thread3. using System. Prioritatea este descresc˘toare a ın a a ˆ lista prezentat˘.1. ¸ s at a pe ma¸ini Intel valori ˆ s ıntre 0 ¸i 31) care determin˘ prioritatea ˆ ansamblul s a ın sistemului de operare a firului respectiv. Incrementer: 997 10. Thread1.Normal. Thread3.Highest.10. O dat˘ ce toate firele de executie de tip foreground ¸ ın ¸ a ¸ se termin˘. Diferenta dintre cele dou˘ posibilit˘¸i o constituie faptul ¸ a at c˘ dac˘ un proces are m˘car un fir de executie ˆ foreground. CLR va executa Abort() pentru fiecare fir de executie de tip a ¸ background (dac˘ mai exist˘ a¸a ceva) ¸i termin˘ procesul. ThreadPriorityLevel.1. aceste nivele fac parte din enumerarea ThreadPriorityLevel : ThreadPriorityLevel.Highest. ThreadPriorityLevel. Thread3. MANAGEMENTUL THREAD–URILOR Thread Thread Thread Thread // .Lowest.Threading.BelowNormal. 10. Thread Thread Thread1. a a s s a Exemplu: using System.

Start(). Thread backgroundThread = new Thread(new ThreadStart(longTest. } Console.maxIterations = maxIterations.Name = "BackgroundThread".RunLoop)).IsBackground = true. foregroundThread.ToString()).Sleep(250). } } Firul din foreground va mentine procesul ˆ executie pˆn˘ cˆnd se termin˘ ¸ ın ¸ a a a a . backgroundThread. public BackgroundTest(int maxIterations) { this. } } class BackgroundTest { int maxIterations. backgroundThread.Start().RunLoop)).".WriteLine("{0} count: {1}". Thread. FIRE DE EXECUTIE ¸ BackgroundTest shortTest = new BackgroundTest(10).CurrentThread. } public void RunLoop() { String threadName = Thread.WriteLine("{0} finished counting. threadName). for(int i = 0. i++) { Console. threadName. foregroundThread. BackgroundTest longTest = new BackgroundTest(50). i. Thread foregroundThread = new Thread(new ThreadStart(shortTest. backgroundThread.Name. i < maxIterations.214 { CURS 10.Name = "ForegroundThread".

CurrentThread.WriteLine( ‘‘Thread {0}. De exemplu.CurrentThread.Sleep(1).. SINCRONIZAREA 215 ciclul s˘u while. ’’. } } . } finally { Console.10.2 Sincronizarea Sincronizarea se ocup˘ cu controlarea accesului la resurse partajate de mai a multe fire de executie.WriteLine( ‘‘Thread {0} interrupted! Cleaning up.Name). Thread.Name). Console.WriteLine( ‘‘Thread {0} Exiting. temp++. counter).Name. Cˆnd acesta se termin˘.CurrentThread. } } catch (ThreadAbortedException) { Console. // increment // simuleza o sarcina oarecare in acest thread Thread. ¸ s ¸ 10. // atribuie valoarea incrementata // variabilei counter // si afiseaza rezultatul counter = temp. se poate cere ca utilizarea unei resurse ¸ anume s˘ se fac˘ la un moment dat de c˘tre un singur fir de executie. instructiunea C# ¸ lock ¸i clasa Monitor. Thread. Incrementer: {1}’’. Vom a a a ¸ discuta aici trei mecanisme de sincronizare: clasa Interlock. chiar dac˘ a a a a ciclul while din firul de executie din background nu ¸i-a terminat executia. Thread. procesul este oprit.2. Exemplele se vor baza pe acces la o resurs˘ partajat˘.’’.. s a a ca mai jos: public void Incrementer( ) { try { while (counter < 1000) { int temp = counter.

S˘ presupunem c˘ pornim dou˘ a ¸ a a a a fire de executie pe baza metodei Incrementer() de mai sus. Primul fir de executie ˆsi a ¸ ı¸ termin˘ munca. t1.Start( ). static void Main( ) { Tester t = new Tester( ).Join( ). FIRE DE EXECUTIE ¸ Cˆmpul counter se initializeaz˘ cu 0. t. t1. Al s doilea fir se activeaz˘ ¸i el. Console. etc. a ¸ s ın Exemplu: using System.Incrementer) ). Thread t2 = new Thread( new ThreadStart(this. using System. pe care o va incrementa apoi.Name = ‘‘ThreadOne’’.Incrementer) ). t2. ˆ locul lui 1. t1.Name = ‘‘ThreadTwo’’. s s a s a s 1. La urm˘toarele iteratii se va afi¸a 2. 4. Se tip˘re¸te astfel 1. } // numara crescator pana la 1000 public void Incrementer( ) { //la fel ca la inceputul sectiunii } . apoi asigneaz˘ valoarea variabilei temporare (1) lui counter a a ¸i o afi¸eaz˘. va citi valoarea (nemodificat˘) lui counter ¸i va as a s atribui aceast˘ valoare unei variabile temporare.Name).IsBackground=true. class Tester { private int counter = 0.WriteLine(‘‘Started thread {0}’’. t2.IsBackground=true. t2. 2.Join( ). 3.Threading. t1.Start( ). Al doilea thread face exact acela¸i lucru. t2. 3. Console.216 CURS 10. 2. Este posibil ¸ s˘ se ˆ ample urm˘toarele: primul thread va citi valoarea lui counter (0) a ıntˆ a ¸i o va atribui unei variabile temporare.DoTest( ). } public void DoTest( ) { Thread t1 = new Thread( new ThreadStart(this.WriteLine(‘‘Started thread {0}’’. t1. t2.Name). 3.

2. Incrementer: Thread ThreadOne.10. care incrementeaz˘ sau decrementeaz˘ o valoare. Putem modifica metoda Incrementer() de mai sus astfel: public void Incrementer( ) { try { while (counter < 1000) { Interlocked. Increment() ¸i Decrea a s ment(). Clasa include dou˘ metode statice. Incrementer: 217 1 2 3 3 4 4 5 5 6 6 Trebuie deci s˘ se realizeze o excludere reciproc˘ a thread–urilor pentru aca a cesul la counter. .1 Clasa Interlocked Incrementarea ¸i decrementarea unei valori este o situatie atˆt de des s ¸ a ˆ alnit˘. ˆ at C# pune la dispozitie o clas˘ special˘ Interlocked pentru o ıntˆ a ıncˆ ¸ a a rezolvare rapid˘.2. Incrementer: Thread ThreadOne. Incrementer: Thread ThreadTwo. Incrementer: Thread ThreadTwo. ˆ a sub un control a a ıns˘ sincronizat. Incrementer: {1}". Incrementer: Thread ThreadTwo. 10. // asigura valoarea decrementata // si afiseaza rezultatul Console. // simuleaza o sarcina in aceasta metoda Thread. SINCRONIZAREA } Ie¸ire: s Started thread ThreadOne Started thread ThreadTwo Thread ThreadOne. Incrementer: Thread ThreadOne. Incrementer: Thread ThreadOne.Sleep(1). Incrementer: Thread ThreadOne.Increment(ref counter). Incrementer: Thread ThreadTwo.WriteLine( "Thread {0}.

218 Thread. dup˘ care o instrutiune sau un grup de instructiuni. Incrementer: Thread ThreadTwo. Incrementer: Thread ThreadTwo. Incrementer: Thread ThreadOne. Incrementer: Thread ThreadTwo. Incrementer: Thread ThreadTwo. Incrementer: Thread ThreadOne. La utilizare. FIRE DE EXECUTIE ¸ } //blocurile catch si finally raman neschimbate } Ie¸irea este cea dorit˘: s a Started thread ThreadOne Started thread ThreadTwo Thread ThreadOne. se specific˘ un obiect pentru care se stabile¸te a s un lock.Name. counter). Sintaxa este: ınl˘ as ¸ ¸ lock(expresie) { instructiuni } Exemplu: metoda Incrementer() se va modifica dup˘ cum urmeaz˘: a a public void Incrementer( ) { try { while (counter < 1000) { lock (this) { . Lock–ul este a ¸ ¸ ˆ aturat la sfˆr¸itul instructiunii/blocului de instrutiuni. } CURS 10. Incrementer: 1 2 3 4 5 6 7 8 10. a ¸ a a a a Un lock marcheaz˘ o sectiune critic˘ a codului.2.2 Instructiunea lock ¸ Exist˘ situatii cˆnd vrem s˘ bloc˘m alte variabile decˆt cele de tip int. producˆnd astfel sincronizare a ¸ a a pentru un obiect. Incrementer: Thread ThreadOne.CurrentThread.

se va apela metoda a Enter. ˆ ın s Inrudit˘ este a metoda PulseAll care anunt˘ toate obiectele blocate pe un anumit obiect de ¸a schimbarea de stare. atunci ˆ a ınseamn˘ c˘ un alt thread este a a ˆ ıntr–o regiune critic˘ a obiectului respectiv. ˆ urma c˘reia este posibil ca un alt fir de executie ın a ¸ care a¸teapt˘ va putea s˘ fie continuat (ordinea de selectare a firelor ce vor s a a fi executate fiind ordinea introducerii ˆ coada de a¸teptare). a Atunci cˆnd se dore¸te s˘ se ˆ a s a ınceap˘ sincronizarea. Thread.3 Clasa Monitor Clasa Monitor contine metode pentru a controla sincronizarea firelor de ¸ executie. care elibereaz˘ monitorul. dˆnd obiectul pentru care se va face blocarea: a Monitor. } } //blocurile catch si finally raman neschimbate } Rezultatele sunt afi¸ate exact ca la sectiunea 10. S˘ presupunem c˘ avem o clas˘ MessageBoard unde fire individuale pot a a a citi ¸i scrie mesaje. s ¸ 219 10. thread–ul curent ar vrea a a s˘ ˆsi continue executia (este ad˘ugat ˆ a ı¸ ¸ a ıntr–o coad˘ de a¸teptare format˘ din a s a fire de executie blocate pe obiect). Terminarea zonei critice se face folosind ¸ metoda Exit() a clasei Monitor. Clasa MessageBoard va avea a a ¸ o metod˘ Reader() ¸i una Writer(). Metoda Pulse() semnaleaz˘ c˘ a avut loc a a o schimbare de stare.1.10.Enter( obiect ). } // atribuie valoarea decrementata // si afiseaza rezultatul Console. temp++. Dac˘ monitorul este nedisponibil.Sleep(1).WriteLine( "Thread {0}. permitˆnd declararea unei zone critice ˆ care la un moment dat ¸ ¸a ın doar un thread trebuie s˘ opereze. SINCRONIZAREA int temp = counter.Name.2. Se mai poate folosi de asemenea a metoda Wait(). informˆnd a a a CLR c˘ atunci cˆnd monitorul devine din nou liber.2. counter = temp. Vom sincroniza accesul la aceast˘ clas˘ astfel ˆ at doar s a a ıncˆ un thread s˘ poat˘ actiona la un moment dat.2. Incrementer: {1}". Thread. dar blocheaz˘ threadul. counter).CurrentThread. a s .

.Enter(this).. messages).’’..220 CURS 10. } finally { Monitor. FIRE DE EXECUTIE ¸ Metoda Reader() determin˘ dac˘ string–ul message contine vreun mesaj a a ¸ valabil. Console. Thread.Wait(this).Threading. Dac˘ nu sunt mesaje ın a ˆ timpul citirii. using System. . Thread. iar metoda Writer() va scrie ˆ acest string. using System. class MessageBoard { private String messages = ‘‘no messages’’ . messages). thread–ul Reader() va intra ˆ stare de a¸teptare folosind ın ın s Wait() pˆn˘ cˆnd metoda Writer() scrie un mesaj ¸i transmite un mesaj via a a a s Pulse() pentru a trezi alte thread–uri.Name).Exit(this).Name. } } public void Writer() { try { Monitor.WriteLine(‘‘{0} Done writing message. Console.Name.CurrentThread..’’.WriteLine(‘‘{0} waiting. Monitor. Thread.CurrentThread. public void Reader() { try { Monitor. } //inseamna ca mesajul s-a schimbat Console.WriteLine(‘‘{0} {1}’’.Enter(this).WriteLine(‘‘{0} {1}’’.CurrentThread. messages = ‘‘Greetings Caroline and Marianne!’’. //daca nu e nici un mesaj atunci asteapta if (messages == ‘‘no messages’’) { Console.

writer. Thread–ul writer va putea acum s˘ blocheze obiectul pentru a scrie mesajul. thread-ul ¸ reader elibereaz˘ obiectul pe care l–a blocat mai ˆ a ınainte prin apelul Wait().2. } finally { Monitor.. a Apoi el cheam˘ metoda Pulse() pentru a semnala firului reader c˘ a ap˘rut a a a o schimbare de stare a obiectului indicat wde this. //semnaleaza threadului de asteptare ca s-a schimbat mesajul Monitor. .. reader. Dar deoarece message nu contine nici un mesaj.Writer)). Thread reader = new Thread(new ThreadStart(myMessageBoard.Name).Pulse(this). WriterThread: Done writing message. reader. el blocheaz˘ a a clasa obeictul de tip MessageBoard.Name = ‘‘WriterThread:’’. } } public static void Main() { MessageBoard myMessageBoard = new MessageBoard(). ceea ce ˆ ınseamn˘ c˘ are acces exclusiv la a a variabila message. thread–ul reader este pornit primul. ReaderThread: Greetings Caroline and Marianne! Dup˘ cum se vede mai sus. } } Ie¸irea este: s ReadrThread: no messages ReaderThread: waiting.Start(). writer.Name = ‘‘ReaderThread:’’.CurrentThread. SINCRONIZAREA 221 Thread.. Thread writer = new Thread( new ThreadStart(myMessageBoard.10..Exit(this).Reader)).Start().

222 CURS 10. FIRE DE EXECUTIE ¸ .

FCL.1) permite crearea de aplicatii Web ¸ folosind platforma . a aa 223 .NET Framework: CLR. • pune la dispozitie un mod de tratare a erorilor unificat (tratarea de ¸ exceptii) ¸i folose¸te controale Web predefinite care se pot executa pe ¸ s s server sau pe client. acest code-behind are posibilitatea de accesare a bazelor a de date sau chiar a codului unmanaged (COM-uri ¸i DLL-uri anterior s existente). executat de a a c˘tre CLR) ˆ loc ca pagina s˘ fie interpretat˘ la fiecare rulare.Curs 11 ASP.NET: ¸a a a aa • unul din marile avantaje ale lui ASP. 6). fiind obiectual ¸i integrat cu toate elementele constitutive ale lui . etc.NET Framework.NET PE. pe serverul open-source Cassini ¸i de asemenea poate fi integrat cu s Apache (folosind Cassini).NET fat˘ de ASP este faptul c˘ ¸a a codul este p˘strat compilat (sub form˘ de cod . se realizeaz˘ separarea p˘rtii de interfat˘ utilizator ın a a¸ ¸a de ceea ce este executat pe server. o aplicatie fiind compus˘ din ¸ a dou˘ p˘rti: pagina afi¸at˘ ˆ browser ¸i pagina de “code-behind”. Rezultatele cele mai bune se obtin totu¸i pe IIS ¸ s 6. a ın a a • modul de realizare este orientat pe obiecte. este una din cele 3 tipuri de aplicatii ¸ creabile sub aceast˘ platform˘. al˘turi de Windows Forms ¸i Web Services.0 (integrat ˆ Windows 2003 Server).NET (actualmente versiunea 1.NET ASP. a a a s Este destina a ˆ ınlocui vechiul ASP (Active Server Pages). care a a¸ s a ın s este o clas˘. ın Enunt˘m mai jos o list˘ neexhaustiv˘ a tr˘s˘turilor ASP. CTS. s BCL. ˆ plus. stateless). Se poate rula pe servere de aplicatii IIS (versiuni ¸ 5. • are un mecanism ˆ ıncorporat care permite p˘strarea st˘rii paginii (chiar a a dac˘ prototlul de comunicare HTTP este f˘r˘ stare.

NET. Web Matrix sau VS. de a altfel).NET • ASP. cu diferente minime fat˘ a ¸ ¸a de programarea aplicatiilor windows.NET iar managementul st˘rii lor este mult ˆ a ımbun˘t˘¸it a at • permite programarea bazat˘ pe evenimente. etc 11.NET O pagin˘ ASP.NET pˆn˘ la repornirea serverului) a a • permite scrierea codului care se va executa pe server ˆ orice limbaj ın . Astfel.NET permite includerea de mai multe funtionalit˘¸i pe controalele ¸ at ASP. alegˆnd automat codul optimizat pentru o colectie de browsere a ¸ • erorile grave ap˘rute ˆ aplicatie ASP. Se poate crea o pagin˘ simpl˘ pe baza urm˘torului continut: a a a ¸ <html> <head> </head> <body> Hello World </body> </html> salvat sub numele de HelloWorld. creat automat la instalarea IISului). de exemplu prin Notepad.NET (varianta recomandat˘.NET nu vor duce la oprirea a ın ¸ serverului Web (dar pot duce la imposibilitatea de a mai executa pagini ASP.NET: C#.1 Ad˘ugarea unui control Web a ˆ Intr-o pagin˘ Web se poate ad˘uga un control pe pagin˘ care s˘ fie generat a a a a de c˘tre serverul IIS ˆ mod adecvat ¸i care poate fi accesat programatic prin a ın s cod. VB.aspx.aspx ˆ directorul r˘d˘cin˘ al site-ului web ın a a a implicit (de obicei c:\Inetpub\wwwroot.224 CURS 11. ASP.NET se poate crea ˆ a ınntr-o multitudine de feluri. Pagina se ˆ ıncarc˘ ˆ browser folosind adresa http://localhost/HelloWorld.1 Anatomia unei pagini ASP. ¸ • este senzitiv la browserul pentru care se face trimiterea codului HTML. ˆ pagina de mai sus se adaug˘ astfel ˆ at s˘ devin˘: ın a ıncˆ a a <html> <head> </head> . a ın 11.1.

acest control va avea ca rezultat un tag de tip span. De remara cat c˘ controlul Web a fos scris ˆ interiorul unui formular. se va genera urm˘torul cod HTML pentru a a a browser (vizibil prin optiunea View Source): ¸ <html> <head> </head> <body> <form name="_ct10" method="post" action="HelloWorld2.1. Atributul runat are ca valoare s ın a cuvˆntul server (singura optiune posibil˘) care spune c˘ respectivul control a ¸ a a se va procesa pe server ¸i nu pe client. 11. aceast˘ schimbare va fi f˘cut˘ pe a a a server prin apelul unei metode scrise ˆ C#: ın <html> <head> </head> <body> <form method="post" runat="server"> <asp:Label id=lblHelloWorld text="Hello World" runat="Server"/> <br> .2 Ad˘ugarea scriptului inline a Vom ad˘uga la pagina anterioar˘ un buton a c˘rui ap˘sare va duce la a a a a schimbarea textului etichetei anterioare. Dup˘ cum se vede ˆ sursa HTML s a ın generat˘.11.aspx" id="_ct10"> <input type="hidden" name="_VIEWSTATE" value="dDw5MjMzODA0MjI7Oz4="/> <span>Hello World</span> </form> </body> </html> ˆ sursa s-a ˆ In ıncorporat un control Web <asp:Label> care prezint˘ propria etatea Text cu textul care va fi af¸at ˆ pagin˘. ANATOMIA UNEI PAGINI ASP. acest lucru este a ın mandatoriu pentru toate controalele Web sau HTML.1.NET <body> <form runat=server> <asp:Label text="Hellow World" runat=server /> </form> </body> </html> 225 Dac˘ se mai ˆ a ıncarc˘ o dat˘ pagina.

In s ¸ a troale (de exemplu continutul unui input de tip text sau de tip select. System. La s ın fiecare cerere urm˘toare a paginii acest input va fi folosit pentru a reinitializa a ¸ ˆ felul acesta este mentinut˘ starea unor concontroalele Web ¸i HTML.1.NET mentine starea unei pagini de la o trim¸ itere la alta c˘tre server. Pentru controlul Button (reprezentat de tag-ul ın <asp:Button\>) s-au asignat textul ¸i metoda care se va apela pe server s (ClickedIt). pentru ¸ care s-a f˘cut alegerea unei optiuni). ASP. E util˘ separarea ˆ ¸a a ıntre cele dou˘ a .EventArgs e) { lblHelloWorld. deoarece asta duce la amestea carea p˘rtii de design al paginii cu procesarea evenimentelor. deoarece serverul mentine starea con¸ troalelor.aspx (lucru care se poate verifica din inspectarea s a codului HTML generat). Erorile de sintax˘ care se fac ˆ codul inline a s ¸ a ın sunt observabile doar la runtime.226 CURS 11.NET are o modalitate extrem de simpl˘ pentru separarea p˘rtii de a a¸ interfat˘ utilizator de cea de cod propriu-zis. Cea mai important˘ este observatia c˘ la codul HTML generat pe client sa ¸ a a ad˘ugat un element input de tip hidden cu numele VIEWSTATE. Acesta a este mecanismul prin care ASP. Pentru a se putea accesa controlul de tip Label pe partea de server. ˆ plus.NET <asp:Button onclick="ClickedIt" text="Submit" runat=Server /> </form> </body> <script Language=C# runat=server> void ClickedIt(object sender. este a¸ ın posibil ca procesarea s˘ fie extrem de consistent˘ iar codul rezultat devine a a greu de urm˘rit ¸i mentinut. Prima dat˘ cˆnd se cere pagina.3 Code-behind Se recomand˘ evitarea scrierii codului inline. ASP. Codul pentru ClickedIt este scris inline ˆ aceea¸i pagin˘ ASP. trebuie ca acestuia s˘ i se asigneze un ID (lblHela loWorld ˆ cazul nostru).Text = "Text schimbat". spre a a aceea¸i pagin˘ HelloWorld. dar vom vedea c˘ aceast˘ metod˘ are o variant˘ mai a a a a bun˘).NET ın s a (pentru simplitate.NET va a a a codifica valoarea tuturor controalelor ¸i le va stoca ˆ acest input ascuns. Remarc˘m c˘ dac˘ s-a ap˘sat pe buton apoi se face refresh pe browser a a a a a se va retransmite “Text schimbat”. ın a ASP. } </script> </html> La ap˘sarea butonului se va face submiterea formularului c˘tre server. precompilarea fiind ˆ acest caz imposibil˘. a ¸ 11.

protected void ClickedIt(object sender. public class HelloWorldCB: System.Text = "Text schimbat" .HelloWorldCB" %> <html> <head> </head> <body> <form method= post runat= server > <asp:Label id="lblHelloWorld" text="Hello World" runat="Server" /> <br> <asp:Button onclick="ClickedIt" text="Submit" runat="Server" /> </form> </body> </html> Pe primul rˆnd s-a scris o directiv˘ ASP.NET 227 aspecte. dar se a a obi¸ uie¸te trecerea lor la ˆ n s ınceputul documentului). using System.NET.UI. using System.cs sau cs (dac˘ e vorba de cod C#) care s a va fi compilat sub forma unui fi¸ier dll depus ˆ directorul bin al aplicatiei s ın ¸ Web. } } } Pagina aspx rezultat˘ va mo¸teni clasa Test1. System. deoarece de partea de interfat˘ se poate ocupa un web-designer. Pentru a se introduce partea de code-behind pentru pagina anterioar˘. se a ¸terge scriptul inline ¸i se modific˘ astfel: s s a <%@ Page Inherits="Test1. Codul executat se va a s ¸ scrie ˆ ıntr-un fi¸ier cu extensia aspx.1. a s .11.Web. using System.Web.UI. Directiva Page precizeaz˘ a ˆ acest caz care este clasa din care se deriveaz˘ pagina curent˘.HelloWorldCB.EventArgs e) { lblHelloWorld. Clasa de ın a a baz˘ se poate declara a¸a: a s namespace Test1 { using System.UI.Web.Page { protected Label lblHelloWorld.WebControls.Web.NET (ele pot fi scrise oriunde. iar ¸a de cea programativ˘ cineva cu cuno¸tinte de . ANATOMIA UNEI PAGINI ASP.

a 11. Aceast˘ metod˘ poate decide dac˘ este cerut˘ de a a a a a c˘tre client pentru prima dat˘ sau este rezultatul unui postback. a 11. s 2. Schita unei metode Load ar fi: at ¸ private void Page_Load(object sender. Are acces la partea de viewstate a paginii (ina a acceibil˘ pentru Init).NET este urm˘torul: ¸a a 1. 4. Se salveaz˘ viewstate a 6. s a a ea este responsabil˘ de asigurarea unei functionalit˘¸i de baz˘ pentru procea ¸ at a sarea de pagini pe server. pe baza a a propriet˘¸ii boolene IsPostBack). aa schimbarea selectiei curente dintr-un dropdown list. Event-handlerele pentru controale sunt apelate (ap˘s˘ri de butoane. Evenimentul de Load este apelat. a a 3.2 Evenimentul Load Se apeleaz˘ dup˘ Init.2.2 Clasa Page Clasa Page este mo¸tenit˘ direct sau indirect de orice pagin˘ ASP.EventArgs e) { //cod care se executa la fiecare cerere if(!IsPostBack) { //cod care trebuie executat doar la prima cerere a paginii //ex: aducerea unor date din baza si popularea unor controale . Aceasta include crearea instantelor controalelor ¸ a ¸ ¸i setarea event-handlerelor.NET. populˆndu-se controalele cu date. Pagina este initializat˘. Ciclul de viat˘ a unei pagin ASP. ASP. Pagina este tradus˘ ˆ HTML (randare) a ın D˘m mai jos cele mai importante evenimente din clasa Page. etc) ¸ 5.NET 11. ˆ ın ¸a In interiorul event-handlerului se creeaz˘ toate controalele de pe pagin˘ ¸i de a as asemenea se face asigneaz˘ event-handlerele pentru acestea.228 CURS 11.1 Evenimentul Init Acest eveniment este primul apelat ˆ ciclul de viat˘ al unei pagini. Partea de viewstate este procesat˘.2. In event-handlerul pentru acest eveniment se ˆ ıncepe programarea logicii paginii. System.

aspx apare: s <%@ Page language="c#" Codebehind="HelloWorld.cs" AutoEventWireup="false" Inherits="HelloWorld. • Codebehind specific˘ numele fi¸ierului surs˘. Aici se dealoc˘ a a resurse precum conexiuni la baza de date. ın ¸ Fi¸ierele care se creeaz˘ automat sunt Web.NET229 } else { //cod care se executa doar daca s-a facut postback //ex: verificarea unor intrari de pe forma } } 11.NET FOLOSIND VISUAL STUDIO.11.3 Evenimentul Unload Este apelat la desc˘rcarea paginii din memoria serverului.aspx. a ın a Pe prima linie a fi¸ierului HelloWorld. s a Ultimul este util pentru cazul ˆ care se dore¸te procesarea evenimentelor de ın s pornire a aplicatiei sau de creare a sesiunii utilizator.NET De¸i se poate scrie ASP. Global.aspx (se folose¸te s aceast˘ denumire ˆ cele ce urmeaz˘). este limbajul ˆ care se scrie ˆ toate blocurile ın ın de cod de tip server.2.asax. este de preferat folosirea s s a a VS.NET ¸i “de mˆn˘”.WebForm1"%> Pentru directiva Page s-au specificat urm˘toarele atribute: a • language cu valoarea c#.3 Crearea unei pagini ASP. CREAREA UNEI PAGINI ASP. de exemplu HelloWorld. 11.NET folosind Visual Studio.NET. ¸ Fi¸ierul Web.NET pentru c˘ permite crearea simpl˘ a fi¸ierelor aspx ¸i a celor de codea a s s behind.3. ˆ plus. legate de sesiune) specis ¸ a fice aplicatiei.asax.NET) s a numit implicit Webform1. acesta se creeaz˘ automat a s a a de c˘tre VS.cs.config.aspx.config contine set˘ri (de securitate. se creeaz˘ ni¸te fi¸iere de set˘ri care ar fi bine s˘ se g˘seasc˘ In a s s a a a a ˆ folderul aplicatiei. ¸ De asemenea s-a creat ¸i un web form (alt nume pentru pagin˘ ASP. din partea de Solution Explorer se poate modifica numele lui cu unul adecvat. Global. a .

NET 7.NET. POSITION: absolute.Web.230 CURS 11. la partea de evenimente ata¸ate butonului se d˘ dublu click a ın s a pe evenimentul Click ˆ partea de code-behind se va genera automat metoda: ın private void Button1_Click(object sender. POSITION: absolute.1"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.0 Transitional//EN" > <HTML> <HEAD> <title>WebForm1</title> <meta name="GENERATOR" Content="Microsoft Visual Studio . ASP. System.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:Label id="lblHelloWorld" style="Z-INDEX: 101. LEFT: 32px.NET • Inherits seteaz˘ clasa care este mo¸tenit˘ de forma web.EventArgs e) .Page. LEFT: 32px. TOP: 24px" runat="server">Hello World</asp:Label> <asp:Button id="Button1" style="Z-INDEX: 102.” Codul generat de designer va fi: <%@ Page language="c#" Codebehind="HelloWorld. iar ˆ partea ın de propriet˘¸i se seteaz˘ pentru ID valoarea lblHelloWorld.WebForm1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. iar pentru text at a valoarea “Hello World. pe partea de HTML a formularului codul va fi: <form id="Form1" method="post" runat="server"> <asp:Label id="lblHelloWorld" style="Z-INDEX: 101.UI.microsoft.cs" AutoEventWireup="false" Inherits="HelloWorld. POSITION: absolute. TOP: 24px" runat="server">Hello World </asp:Label> </form> </body> </HTML> Se trage apoi un control de tip buton pe form˘ pentru care ID-ul implicit este a Button1 iar textul va fi setat la “Buton”.aspx. aceast˘ clas˘ a s a a a trebuie s˘ fie derivat˘ direct sau indirect din clasa System. TOP: 24px" runat="server" Text="Buton"></asp:Button> </form> Dac˘ ˆ toolbox. LEFT: 128px. a a Se trage de pe toolbox un control Label pe forma ASP.

s a Trimiterea formularului prin cod client s-ar face astfel: <script language="javascript"> function SubmitTheForm() . Exist˘ dou˘ modalit˘¸i de realizarea a acestei trimiteri ˆ a a at ınapoi: prin folosirea unor elemente de tip <input type="submit"> sau <input type="image"> respectiv prin script executat pe client. dac˘ se trage pe form˘ a a un buton. a iar pagina nou˘ va fi trimis˘ c˘tre browser.1 Controale server Postback Postback apare de cˆte ori se transmite pagina de la client ˆ a ınapoi la server.4. De exemplu.aspx" id="Form1"> <input type="submit" name="Button1" value="Button 1" id="Button1" /> </form> Dac˘ pentru un formular nu se specific˘ partea de action. CONTROALE SERVER { } 231 atunci cˆnd butonul este ap˘sat se face o submitere a formularului c˘tre a a a server ¸i codul continut ˆ metoda de mai sus va fi executat. aceasta implicit va a a fi accea¸i pagin˘.4. codul generat de designer va fi: <form method="post" runat="server" ID="Form1"> <asp:Button id="Button1" runat="server" Text="Button 1"></asp:Button> </form> iar pe browser se va genera: <form name="Form1" method="post" action="MyASPNETPage. Reˆ a a a ımprosp˘t˘ri succesive ale aa paginii (refresh) vor duce la afi¸area aceluia¸i “Text schimbat”.4 11. Codul va fi: s ¸ ın private void Button1_Click(object sender. } La ap˘sarea butonului textul din componenta lblHelloWorld se va schimba.EventArgs e) { lblHelloWorld.11. deoarece s s viewstate-ul contine valoarea modificat˘ de ap˘sarea butonului.Text = "Text schimbat". ¸ a a 11. System.

forms["Form1"].submit(). POSITION: absolute. LEFT: 312px.appName.NET iar proprietatea onclick a unui contro de tip HTML se seteaz˘ la valoarea a SubmitTheForm(): <INPUT style="Z-INDEX: 103. } </script> CURS 11. POSITION: absolute.Form1. } unde EVENTTARGET ¸i EVENTARGUMENT sunt dou˘ cˆmpuri ass a a cunse.__EVENTTARGET. } else { theform = document. TOP: 104px" type="button" value="Button" onclick="SubmitTheForm()"> ˆ cazul controalelor Web de tip server a c˘ror modificare de stare trebuie s˘ In a a duc˘ la postback (de exemplu la selectarea unui item dintr-un combobox).submit(). eventArgument) { var theform. if (window.toLowerCase(). se a seteaz˘ proprietatea AutoPostBack pe true.__EVENTARGUMENT.value = eventTarget.indexOf("microsoft") > -1) { theform = document. LEFT: 80px.’’)" language="javascript" id="DropDownList1" style="Z-INDEX: 104.navigator. se seteaz˘ o metod˘ pentru evenia a a mentul de schimbare a continutului (ˆ cazul nostru: SelectedIndexChanged ) ¸ ın iar pagina HTML generat˘ pe client va contine o functie javaScript de suba ¸ ¸ mitere a formularului: function __doPostBack(eventTarget.forms["Form1"]. } theform.value = eventArgument. TOP: 120px"> <option value="1">opt 1</option> <option value="2">opt 2</option> </select> .join(":").split("$"). ASP. Combobox-ul arat˘ astfel ˆ codul HTML client: a ın <select name="DropDownList1" onchange="__doPostBack(’DropDownList1’. theform.232 { document. theform.

.2 Data Binding Data Binding permite legarea unei propriet˘¸i a unui control la o surs˘ at a de date.browserul ¸tie Html 4 sau mai mult. CONTROALE WEB 233 11.se presupune c˘ browserul ¸tie doar Html 3. s Toate controalele care au posibilit˘¸i de Data Binding implementeaz˘ o at a metod˘ numit˘ DataBind(). Este important de retinut c˘ expresiile Data Binding ¸i pro¸ a s priet˘¸ile DataSource nu sunt evaluate pˆn˘ cˆnd nu se apeleaz˘ metoda at a a a a DataBind() ale controalelor cu care sunt asociate. Aceast˘ metod˘ se aplic˘ pentru orice control care nu este a a a list˘ precum Label.UI. Cˆnd Data Binding se face pentru a a un control de tip list˘ (DropDownList sau CheckBoxList) se va folosi propria etatea DataSource a controlului la o surs˘ de date oarecare (e. evenimente precum Init.aspx. CheckBox.se va face autodetectarea browserului • DownLevel .Web.11. care cˆnd este ınsu¸ a a apelat˘ va duce la apelul tuturor metodelor DataBind() pentru controalele a copil. CSS. Clasa Page are o proprietate nestatic˘ numit˘ ClientTarget care permite definirea a a browserului client. are o implementare de metod˘ DataBind(). Aceasta se ocup˘ de evaluarea expresiilor de a a a biding ˆ fi¸ierul . Load. a s a ¸ Nu exist˘ o relatie univoc˘ ˆ a ¸ a ıntre controale web ¸i elemente Html. viewstate. DataSet).Web. Deoarece Page este el ˆ si un control.UI.4. EcmaScript. TextBox.aspx sau ˆ ın ¸ ın s ın code-behind.aspx sau pentru sursele de date specificate ˆ proprietatea ın s ın DataSource.WebControls care este derivat din System. Aceast˘ legare se poate face a ın a scriind expresii ˆ interiorrul unei declaratii de control ˆ fi¸ierul . precum un cˆmp ˆ baza de date. Unload. ci cons troalele web vor randa pe parte de client cod Html specific browserului.g. 11.5 Controale Web Controalele Web reprezint˘ o modalitate u¸oar˘ de a interationa cu serverul. Valorile pentru proprietate sunt: • Auto .5.2 sau mai a s putin ¸ • UpLevel . Mis crosoft Document Object Model Orice control Web este derivat din System. Aceasta din urm˘ pune la dispozitie a ¸ partea de Data Binding. Pentru a se lega direct ˆ fi¸ierul . a Aceasta paote fi f˘cut˘ ˆ partea de code-behind sau ˆ a a ın ıntr-un bloc de tip script din fi¸ierul .aspx se folose¸te tag-ul <%# %> (expresie ın s s Data Binding).Control.

System. Se ¸ genereaz˘ pe browser ca fiind un element de tip span. TOP: 10px" runat="server" text="<%# DateTime.ToString() %>"> </asp:Label> Pentru ca valoarea s˘ fie efectiv calculat˘ ¸i afi¸at˘ pe parte de browser a a s s a trebuie chemat˘ metoda DataBind() pentru obiectul etichet˘. astfel ˆ at a a ¸ ıncˆ s˘ se poat˘ determina care a fost butonul ap˘sat. atunci se poate scrie: a s <asp:Label id=Label1 style="Z-INDEX: 101. pe baza unui event handler definit ˆ code-behind. LEFT: 10px.Web.NET etc.5.UI. ceea ce ar putea genera urm˘torul cod ˆ designer: at a ın <asp:Label id=Label1 runat="server" Width="70px" Height="50px"> This is a label </asp:Label> Dac˘ se dore¸te folosirea DataBinding.1 Label Contine text de tip read-only. System. acest lucru se a a poate face ˆ partea de ˆ arcare a paginii: ın ınc˘ protected void Page_Load(object sender. Clasa WebControl contine propriet˘¸i de stil precum bacgkround. } 11. POSITION: absolute.Now. Event at s handlerul pentru butoane poate s˘ fie: a private void Button_Command(object sender. Pentru crearea unei a etichete cu text predefinit se trage un control Web de pe toolbar ¸i se pot s seta propriet˘¸i ale lui. 11.5. ASP.234 CURS 11.EventArgs e) { Label1.WebControls.2 Button Permite crearea unui buron de tip submit ¸i care poate s˘ determine s a executarea unei metode C# pe parte de client. ın ˆ cazul ˆ care se dore¸te crearea mai multor butoane care s˘ fie procesate In ın s a pe server. asignat static sau prin Data Binding. Acest lucru se face prin a a a propriet˘¸ile CommandName ¸i CommandArgument de tip string.CommandEventArgs e) .DataBind(). ¸ at width. e nevoie de un mecanism care s˘ fac˘ diferentierea lor. height.

AutoPostBack ¸i s un eveniment TextChanged. a ¸ a 11. TextAlign. mecanismul se bazeaz˘ pe accea¸i funtie s a s ¸ Javascript ca la LinkButton.5. Wrap. pagina va fi automat retransmis˘ la server dac˘ se iese din controlul a a curent ¸i textul a fost schimbat.5 CheckBox Determin˘ aparitia unui checkbox. propriet˘¸ile de interes sunt Checked. s at s Lista de optiuni se poate crea fie prin introducere direct˘ ˆ proprietatea ¸ a ın Items. Prezint˘ propriet˘¸i de a at tipul Columns. CONTROALE WEB { //This Is a Command event handler } 235 unde obiectul e are propriet˘¸ile CommandName ¸i CommandArgument care at s vor da valorile setate pentru controale.11. fie prin Data Binding. Evenimentul care se pate detecta este SelectedIndexChanged ¸i se poate procesa pe server. Rows. Toate item-urile continute sunt accesibile via proprietatea Items de tip ¸ ListItemCollection. 11. codul Html generat va fi de forma <a> iar la a s ap˘sare va apela functia Javascript __doPostBack prezentat˘ mai sus. MultiLine sau Password. a ¸ at Text. ReadOnly.6 RadioButton Derivat˘ din CheckBox.7 DropDownList Permite crearea unei liste de optiuni stocate sub numele de nume ¸i val¸ s oare. Fiecare element al unei astfel de coletii este de tip Lis¸ tItem ¸i are propriet˘¸ile Text.5. 11.5. Dac˘ proprietatea AutoPostBack este setat˘ la a a true. Text.5. are ˆ plus proprietatea GroupName care permite a ın gruparea mai multor astfel de butoane.5.4 TextBox D˘ posibilitatea de a introduce text ˆ a ıntr-un formular. Value de tip String ¸i Selected de tip boolean. MaxLength. s . 11.5.3 LinkButton Se comport˘ ca ¸i un buton. Se poate folosi ˆ ın trei moduri: SingleLine. 11. AutoPostBack iar evenimentul detectat este CheckedChanged.

NET . ASP.236 CURS 11.

chiar dac˘ au fost efectuate valid˘ri primare pe a s a a client. atunci pot ap˘rea deplas˘ri ale componentelor a a a de pe pagin˘ pentru a face loc textului de eroare. celelalte returnˆnd a a automat valoare de adev˘r dac˘ controlul de intrare nu contine nimic. a a ¸ Orice astfel de control de validare este derivat din clasa BaseValidator.NET (2) 12. dac˘ proprietatea este a setat˘ pe false se va face validarea doar pe server. s ın Proprietatea EnableClientScript setat˘ pe true va duce la generarea de a cod scripting pentru client (JavaScript sau VBScript). Pentru un client de tip nons DHTML.1 Controale de validare Controalele de validare sunt utilizate pentru a face verificari asupra ˆ ındeplinirii unor conditii pentru continutul controalelor de introducere a datelor. pentru un asemenea control nu se va genera nici un cod scripting client. se poate folosi un control de tipul RequiredFieldValidator ¸i altul care s˘ valideze continutul folosind expresii regulate. ci atunci cˆnd formularul este trimis c˘tre server se va face testare vaa a 237 . Poate avea a a a s valorile Static ¸i Dynamic: ˆ primul caz se rezerv˘ suficient spatiu pentru s ın a ¸ mesajul de eroare. Mesajul de eroare se a define¸te ˆ proprietatea ErrorMessage. Aceast˘ ¸ ¸ a validare se poate face pe server sau (de preferat ˆ majoritatea cazurilor) pe ın client (dac˘ acesta suport˘ DHTML). Trebuie retinut faptul a ¸ c˘ validarea se face ˆ a ıntotdeauna ¸i pe server. doar s a ¸ primul control poate determina dac˘ s-a introdus ceva.Curs 12 ASP. care prezint˘ proprietatea ControlToValidate ˆ care se depune ca valoare IDa ın ul controlului pentru care se face validarea. ˆ al doilea caz dac˘ a ın a mesajul de eroare este ar˘tat. Unui control de preluare a datelor i se pot asocia oricˆte controale a de validare. Valid˘ri suplimentare mai complexe a a a pot ap˘rea ¸i pe server. Proprietatea Display determin˘ a dac˘ se rezerv˘ loc pe pagin˘ pentru a se afi¸a mesajul de eroare. De exemplu. chiar dac˘ acesta nu este vizibil.

238 CURS 12. ta 12.NET (2) lidit˘¸ii datelor introduse. Valorile s ın minime ¸i maxime admise se dau ˆ propriet˘¸ile MinimumValue ¸i Maxis ın at s mumValue. etc. CompareValidator. ASP. a se vedea ¸i www. a ˆ acest context spunem c˘ clasa Page contine o proprietate IsValid care In a ¸ va fi setat˘ la true dac˘ toate validatoarele sunt ˆ a a ındeplinite pe parte de server sau false ˆ caz contrar. URL.4 CompareValidator Se folose¸te pentru a compara continutul unui control cu continutul als ¸ ¸ tui control sau cu o valoare fix˘. CustomValidator. Dac˘ se dore¸te compararea cu a a a s 1 Pentru o coletie bogat˘ de expresii regulate.3 RangeValidator Verific˘ dac˘ valoarea dintr-o intrare este cuprins˘ ˆ a a a ıntre un minim ¸i un s maxim. pe parte de server se va folosi clasa Regex 1 . 12. Integer. 12. Double.2 RegularExpressionValidator Verific˘ pe baza unei expresii regulate dac˘ valoarea introdus˘ ˆ a a a ıntr-un cˆmp este corect˘. Pe parte de client se va folosi sintax˘ de regex-uri de a a a tip JavaScript.1. Pentru continut ¸i extreme tipul poate fi String. 12.1. specificat ˆ proprietatea Type a controlului. predefinit˘. RegularExpressionValidator. ValidationSummary.com ¸ a s . dac˘ ceva nu corespunde criteriilor se va retrimite at a pagina c˘tre client ˆ a ımpreun˘ cu mesajele de eroare scrise. RangeValidator.1. ˆ Visual Studio In sunt definite cˆteva expresii regulate care se pot aplica pentru diferite scopuri: a adrese de email. ın Controalele de validare sunt: RequiredFieldValidator. numere de telefoane din diverse ¸˘ri. ¸ s Date ¸i Currency.1.regexlib. Codul JavaScript care ın se efectueaz˘ aceste valid˘ri este scris ˆ fi¸ierul surs˘ C:\Inetpub\wwwroot\ a a ın s a aspnet client\system web\1 1 4322\WebUIValidation.js. Dac˘ se ˆ a ıncearc˘ submiterea formularului iar cˆmpul pentru care s-a setat a a vaidatorul nu are valoare introdus˘ se va semnala eroare prin aparitia mesajua ¸ lui definit de utilizator ˆ proprietatea ErrorMessage.1 RequiredFieldValidator Forteaz˘ utilizatorul s˘ introduc˘ ceva ˆ ¸ a a a ıntr-un control de introducere.

12. se seteaz˘ adecvat proprietatea ControlToComa pare. care verific˘ validitatea datei calendaristice specifia cate).Value == "JoeHealy" || args. CONTROALE DE VALIDARE 239 valoarea dintr-un alt control. Proprietatea Operator specific˘ operatorul folosit la comparare: Equal (implicit).IsValid = true. LessThanEqual.1.Value == "SpikePierson" || args. ServerValidateEventArgs args) Al doilea parametru are proprietatea Value care d˘ acces pe server la valoarea a introdus˘ pe client ¸i proprietatea IsValid de tip bool care trebuie setat˘ pe a s a true dac˘ validarea s-a f˘cut cu succes sau false ˆ caz contrar. iar dac˘ se face compararea cu o valoare predefinit˘ atunci se seteaz˘ a a a proprietatea ValueToCompare.12. } else { args. } } . atunci se va seta ˆ mod adecvat proprietatea ın ClientValidationFunction. GreaterThanEqual.5 CustomValidator Permite crearea de validatoare de c˘tre programator. ServerValidateEventArgs args) { if (args. De asemenea se poate specifica tipul de dat˘ a pentru care se face compararea.1. NotEqual. Dac˘ ˆ a se dore¸te validarea ¸i a ıns˘ s s pe client folosind JavaScript. a at Motivul pentru care s-ar folosi un asemenea validator ar fi c˘ verificarea a se poate face numai pe server (de exemplu se verifica dac˘ numele si parola a unui utilizator se regasesc in baza de date).IsValid = false. Pentru validarea pe server trebuie dat un a a s delegat de tipul: void HandlerName (object source. ¸i DataTypes Check (operator unar.Value == "AndyJohnston") { args. a GreaterThan. care se pot executa a atˆt pe client cˆt ¸i pe server. ca la RangeValidator. Exemplu: pentru validarea pe server a valorii introduse ˆ ıntr-un cˆmp. se a poate scrie codul C#: private void vldUserIDCstm_ServerValidate(object source. Aceast˘ a a ın a valoare afecteaz˘ valoarea propriet˘¸ii IsValid a obiectului de tip Page. LessThan.

} } </script> Numele functiei JavaScript este setat ˆ proprietatea ClientValidationFunc¸ ın tion. Este folosit pentru a afi¸a mesajele de eroare pentru toate controalele s de validare ˆ ıntr-un singur loc. 12. atunci se vor afi¸a mesajele de eroare ˆ pagina HTML.IsValid=false.2 Comunicarea cu browserul Pentru trimiterea de date c˘tre client se poate folosi pe parte de server a obiectul predefinit Response de tip HttpResponse. atunci va ap˘rea a a o fereastr˘ cu lista de erori.IsValid=true. ˆ acest din urm˘ caz. args) { if (args. se poate scrie codul urm˘tor s s a la sfˆr¸itul paginii aspx: as <script language="JavaScript"> function vldUserIDCstm_ClientValidate(source. } else { args. a ın a 12.NET pune la s .Value = "JoeHealy" || args. SingleParagraph. s ın a ˆ plus. ın Ele pot fi afi¸ate ˆ pagin˘ de orice browser.Value = "AndyJohnston") { args. pentru un browser de tip a ın a DownLevel mesajul nu va fi ar˘tat ˆ fereastr˘. Dac˘ proprietatea de tip bool ShowSummary este a a setat˘ pe true. De asemenea exist˘ proprietatea a HeaderText care permite afi¸area unui antet deasupra listei de erori.6 ValidationSummary Nu este un control de validare propriu zis. BulletList. avˆnd valorile ın s a posibile: List.Value = "SpikePierson" || args. fie el UpLevel fie DownLevel. ASP. fiind derivat din clasa WebControl. Proprietatea DisplayMode este folosit˘ pentru a a controla formatul ˆ care se vor afi¸a mesajele de eroare.NET (2) Pentru a se face aceea¸i verificare ¸i pe client. un browser UpLevel poate s˘ afi¸eze mesajul (¸i) ˆ In a s s ıntr-o fereastr˘ de a eroare creat˘ de browser. De¸i ASP. s Mesajele de eroare pot fi afi¸ate ˆ s ıntr-unul din 2 moduri sau ˆ ambele.1.240 CURS 12. Dac˘ a s ın a proprietatea de tip bool ShowMessageBox este pus˘ pe true.

2 Redirectarea Se folose¸te pentru cazul ˆ care pagina care se trimite clientului nu este s ın cea curent˘. Utilitatea unei asemenea metode este limitat˘. 3.Now.12.2. DateTime. Response este util pentru: a 1. via ¸ s a metoda WriteFile. De exemplu. COMUNICAREA CU BROWSERUL 241 dispozitie mecanisme suficient de complexe pentru a nu necesita folosiera ¸ masiv˘ a acestui mecanism.EventArgs e) { Response.Format("<i>The time is: <b>{0}</b></i><br>".Redirect("http://mysite. modificarea mecanismului de buffering. Redirectarea trebuie f˘cut˘ ˆ a a a a ınainte ca vreun header s˘ fie trimis c˘tre client. System. f˘r˘ a se trimite cod c˘tre browser a aa a care s˘ ˆ determine pe acesta s˘ cear˘ o alt˘ resurs˘. DateTime. a a Exemplu: Response.Write(string. a ıl a a a a . managementul mecanismului de caching 12. s a Exemplu: protected void Page_Load(object sender. Aceast˘ redirectare are loc de pe server.Format("The date is: {0}<br>". redirectarea clientului. } De asemenea se permite trimiterea continutului unor fi¸iere c˘te browser. pagini foarte simple sau debugging. dar exist˘ situatii ˆ care calea a a ¸ ın se dovede¸te a fi bun˘.com/myBusiness"). ci o alta.ToShortDateString())). Response.Write(string.1 Generarea programatic˘ continutului a ¸ ˆ unele cazuri r˘spunsul care se trimite de la server la browserul client In a poate fi suficient de simplu pentru a nu necesita utilizarea de controale. 12. 2.2. pentru cazul ˆ care se dore¸te redirectarea a ın s utilizatorului c˘ter o pagin˘ de login.ToShortTimeString())).Now.2. 4.

Add("userid".242 CURS 12. Exist˘ 4 clase de lucru cu cookie-urile: ¸ a • HttpCookie • HttpCookieCollection • HttpResponse • HttpRequest Obiectul Response are o colectie numit˘ Cookies.EventArgs e) { HttpCookie tempcookie = new HttpCookie("myCookie").ToDateTime("24/05/05 16:00"). Cˆnd un browser face o ¸ a a cerere c˘tre un server. a ın Exemplu de creare a unui cookie de tip sesiune: protected void Page_Load(object sender. a ın Atunci cˆnd se trimite un cookie de pe server pe client se poate prea ciza dac˘ acesta va fi valabil doar pe perioada cˆt este deschis browserul a a (a¸a-numitele cookie-uri de sesiune) sau ¸i dup˘ ce browserul este ˆ s s a ınchis (cookie-uri persistente . De¸i nu reprezint˘ a ¸ a s a un mecanism garantat pentru lucrul cu clientul.3 Cookies Cookie-urile reprezint˘ informatie stocat˘ pe client. va trimite prin intermediul headerelor toat˘ colectia a a ¸ de cookie-uri care apartin acelui site. ˆ unele cazuri pot fi suficient ın de utile pentru o aplicatie.Expires = Convert. } Pentru crearea unui cookie persistent. tempcookie. "1250"). ASP.Cookies. perscookie.Values.rezist˘ pˆn˘ la o dat˘ a expir˘rii setat˘ sau pentru a a a a a a totdeauna). Cele de tip sesiune nu au setat ¸ ¸ nici un timp de expirare (¸i se retin ˆ memoria RAM a calculatorului). System. System.Add(tempcookie). Aceast˘ colectie se ˆ ¸ a ¸ ıncarc˘ ˆ Cookies. se poate proceda ca mai jos: protected void Page_Load(object sender. pe s ¸ ın cˆnd celelalte pot avea un timp setat ˆ viitor (fiind persistate pe disc). Response.EventArgs e) { HttpCookie perscookie = new HttpCookie("myCookie"). a Diferenta dintre cele dou˘ din punct de vedere programatic const˘ ˆ ¸ a a ın absenta sau prezenta unui timp de expirare.NET (2) 12. un cont fiind folosit de c˘tre mai multi. al doilea a ¸ tip se poate folosi pentru stocarea informatiilor (precum preferintele) de la o ¸ ¸ vizit˘ la alta. . Primul tip de cookie-uri sunt utile ˆ medii ˆ care nu exist˘ ın ın a intimitate a utilizatorului.

NET\Framework\Version\CONFIG. Response.apelat ori de cˆte ori un client cere o pagin˘ a a oarecare de la server. este compilat ca o clas˘ care este derivat˘ a s ın a a ¸ a a din HttpApplication.NET (mai exact. fiind recompilat˘ automat la fiecare modificare a sa. folosit˘ pentru initializarea unor a a a ¸ a ¸ resurse (grupuri de conexiuni..config unei aplicatii a ın ¸ ASP.config aflat ˆ dioreca a a s ın torul %windir%\Microsoft.4 Fi¸ierul de configurare al aplicatiei Web s ¸ Diverse set˘ri ale aplicatiei pot fi mentinute ˆ a ¸ ¸ ıntr-un fi¸ier de tip XML nus mit Web.. FISIERUL DE CONFIGURARE AL APLICATIEI WEB ¸ ¸ perscookie.Cookies. Structura ¸i modul de accesare a continutului acestuia este s ¸ asem˘n˘toare cu cea prezentat˘ ˆ sectiunea 8.Add("userid". etc care sunt accesate s de c˘tre p˘rti din aplicatie).5 Fi¸ierul global.ori de cˆte ori se porne¸te o sesiune a s • Application BeginRequest . } 12. ¸ a a a La r˘d˘cina acestei ierarhii se afl˘ fi¸ierul machine.NET.Values["userid"]. if (cookie != null) { string s = cookie. pentru obiectul reprezentˆnd aplicatia). Fi¸ierul ¸ a ¸ s se g˘se¸te ˆ r˘d˘cina aplicatiei.4.ToString(). } 243 Accesarea acestui cookie se face pe server prin intermediul obiectului Request: HttpCookie cookie = Request.Add(perscookie). 12. a Metodele care se pot implementa ˆ aceast˘ clas˘ sunt: ın a a • Application Start .config. s-ar putea folosi la contorizarea num˘rului de a accese la pagin˘ a . Deosebit este ˆ a fapa a a ın ¸ ıns˘ tul pentru o aplicatie Web aceast˘ configurare respect˘ o anumit˘ ierarhie.4.asax s Este un fi¸ier optional structurat XML care prezint˘ set˘ri relative la s ¸ a a aplicatia ASP. .12.Values. a a¸ ¸ • Session Start . "1250"). Set˘rile de a aici pot fi suprascrise de set˘ri aflate ˆ directoarele Web.Cookies["myCookie"].4.apelat˘ atunci cˆnd un client cere pentru prima a a oar˘ o pagin˘ de la aceast˘ aplicatie. valori din regi¸tri.

apare la o resetare a serverului sau atunci cˆnd se a recompileaz˘ aplicatia ASP. s a s a Stocarea unei valori ˆ sesiune trebuie s˘ se fac˘ folosind o cheie (unic˘ ın a a a pe acea sesiune) ¸i o valoare ata¸at˘ (de ori ce tip). exist˘ alternativa de a stoca sesiunile pe un alt server sau chiar pe un a server SQL. se cere id-ul stocat ˆ cookie-ul a a ın de pe client ¸i se afl˘ care este sesiunea ata¸at˘. Dac˘ cheia username nu exist˘. Golirea sesiunii se face cu Session. De fiecare dat˘ cˆnd se cere o pagin˘ a a a a de la server (dup˘ ce sesiunea a fost creat˘).NET (2) • Application EndRequest . ASP.244 CURS 12. a ¸ 12. etc). . Mention˘m c˘ ˆ sesiune se pot stoca orice obiecte. Dac˘ serverul web se reporne¸te. Aceast˘ sesiune a este ata¸at˘ doar browserului care a cerut crearea ei. ID-ul acelui ¸ s aa client.6 Managementul sesiunii Sesiunea este un mecansim prin care se creeaz˘ impresia unei conexiuni a permanente de la client la server.apelat˘ la fiecare cerere de autentifia care a unui utilizator • Application Error . Exemplu: s s a Session["username"] = "jsmiley". Stergerea unei chei ¸i a valori ata¸ate din sesiune se face folosind ¸ s s metodele Session. se va crea ¸i i se va ata¸a string-ul numit. Session. atunci vechea sesiune este inaccesibil˘.Clear().RemoveAt(int index).Remove(String key).RemoveAll() sau Session. a a s s dac˘ exist˘.la terminarea unei sesiuni prin expirare • Application End . valoarea sa se va suprascrie. O sesiune este stocat˘ pe server ¸i va a s retine toate obiectele necesare bunei function˘ri pe perioada respectiv˘ (de ¸ ¸ a a exemplu poate contine co¸ul de cump˘r˘turi pentru un client. toate valorile din acea sesiune se a s pierd.apelat la sfˆr¸itul oric˘rei cereri c˘tre server as a a • Application AuthenticateRequest . a a ¸ se creeaz˘ un obiect de sesiune pe server identificat printr-un num˘r unic a a care este de asemenea trimis clientului printr-un cookie. Recuperarea valorii anterioare se a a face cu: String uname = (string)Session["username"]. nu doar ¸iruri de ca¸ a a ın s ractere. Ori de cˆte ori un client cere prima pagin˘ a unei aplicatii Web.apelat˘ ori de cˆte ori apare o eroare care nu a fost a a procesat˘ a • Session End . dac˘ acesta se ˆ s a a ınchide.NET.

ci pe baza unui cˆmp de tip hidden din a pagina HTML trimis˘ clientului. . nivelul de acces ¸ la date. iar accesarea lui prin: MyObject x = Application["x"].1 Application Obiectul Application este foarte asem˘n˘tor cu Session. cu deosebirea c˘ a a a nu este unic pentru fiecare sesiune utilizator.pentru a permite separarea muncii ˆ ıntre web designer ¸i programator. Spre deosebire de obiectul Session care poate stoca orice tip de obiect. 12. a • separarea codului de prezentare .7. footer.7 ViewState ViewState reprezint˘ o colectie de valori care se stocheaz˘ pe client. . dar a ¸ a nu prin intermediul cookie-urilor. separarea pe mai multe nivele u¸ureaz˘ s s a mentinerea codului ¸i schimbarea lui.12. Stocarea de valori se face prin: a Application["x"] = new MyObject(). Este folosit˘ ˆ special pentru a retine a a ın ¸ valorile controalelor Web de-a lungul mai multor post-back-uri.8 Alte puncte de interes ˆ aplicatii ASP. este sugerat˘ folosirea a cel putin ¸ s a ¸ 3 nivele: interfata utilizator.NET ın ¸ • crearea controalelor utilizator . 12. utile pentru orice ¸ sesiune (valori din regi¸tri sau valori imuabile care nu trebuie citite de fiecare s dat˘).a paginilor care sunt convertite ˆ conın troale pentru a permite reutilizarea lor mai simpl˘ . obiectul ViewState (de tip StateBag) poate s˘ contin˘ doar string-uri. Se poate ¸terge selectiv din obiectul ViewState prin metoda Remove(String s cheie). nivelul de business logic.7. ci pentru ˆ ıntreag aplicatie.. VIEWSTATE 245 12. Este ¸ utilizat pentru mentinearea unor obiecte cu caracter global. a ¸ a Exemplu: ViewState["uname"] = "Joe". String suname = (string)ViewState["uname"].ex: header.

• folosirea protocoalelor de comunicatie securizate (SSL) ¸ • folosirea serviciilor Web . exist˘ totu¸i un seg¸ a a s ment bine definit care cere astfel de aplicatii.NET Passport.diverse forme de securitate: formulare. bazate ın pe XML ¸i protocoale de comunicatie larg r˘spˆndite. Design-ul specific ¸i ¸ s capabilit˘¸ile unui astfel de browser pot ridica probleme noi. .246 CURS 12. a .NET (2) • crearea de aplicatii web pentru dispozitive mobile. un serviciu Web s ¸ a a este independent de platform˘. • autentificarea .servicii care se pot accesa ˆ Internet.pentru optimizarea accesului la resurse. ASP. at • politici de caching . de¸i la ora actual˘ ¸ s a piata de dispozitive mobile este relativ redus˘.

• interfete puternic tipizate . 247 . s pentru a evita “reinventarea rotii” ¸ • acces multilimbaj . cˆt ¸i la nivelul clientului. a a a a 13.1 Componentele unui WS Principalele blocuri componente ale unui serviciu Web sunt redate ˆ ın figura 13. Un client poate accesa un serviciu Web folosind standarde a Internet. Aceste tipuri de date ar trebui s˘ se poat˘ mapa rezonabil peste tipurile de date folosite a a de limbajele procedurale existente. • folosirea standardelor Internet .implementarea unui SW trebuie s˘ a se bazeze pe standardele ¸i protocoalele de comunicare deja existente.1. ın a s • posibilitate de integrare ˆ orice infrastructur˘ distribuit˘ .nu trebuie s˘ existe ambiguitate relativ la ¸ a tipul de date trimise sau primite spre/de la un SW.1.Curs 13 Servicii Web 13.un SW trebuie s˘ permit˘ comunicarea ˆ a a ıntre orice platforme.un SW nu trebuie s˘ reduc˘ aria limbajelor care le a a pot utiliza.un SW nu ın a a trebuie s˘ fie strˆns cuplat de o anumit˘ infrastructur˘ de comunicare.1 Generalit˘¸i at Un serviciu Web (SW) expune o interfat˘ de invocare a unei activit˘¸i de ¸a at c˘tre un client. transparenta trebuie s˘ se manifeste atˆt la nivelul limba¸ a a jului ˆ care s-a creat SW. Un serviciu web rezolv˘ urm˘toarele probleme: a a • interoperabilitate .

care s˘ nu necesite a set˘ri speciale de securitate.dup˘ ce s-a rezolvat problema de la punctul precedent.necesar a fi precizat pentru a se putea codifica ˆ ıntr-un mod convenabil toat˘ conversatia ˆ a ¸ ıntre client ¸i SW. Descoperirea poate fi realizat˘ prin intemediul unor direca toare centralizate sau prin alte metode ad-hoc. SERVICII WEB • Descoperirea . • Codificarea .1 Discutii asupra blocurilor componente ¸ Protocolul de transport O aplicatie bazat˘ pe SW poate s˘ fie folosit˘ atˆt ˆ LAN cˆt ¸i ˆ ¸ a a a a ın a s ıntr-o retea de mare ˆ ¸ ıntindere.proces numit a ¸ descoperire. • Descrierea .2 Schema de codificare XML reprezint˘ alegerea natural˘ pentru codificarea mesajelor dintre a a client ¸i server. SMTP ¸i HTTP sunt portocoale care nu cer o configurare In s special˘ a firewall-urilor care delimiteaz˘ o retea. • Formatul mesajelor . Protocoale precum HTTP sau SMTP sunt testate din punct de vedere al serviciilor pe care ˆ ofer˘.2 13. s • Transportul . deoarece este structurat (f˘cˆnd procesarea sa u¸oar˘) ¸i s a a s a s . ¸ Descrierea reprezint˘ metadate structurate despre interfata ce urmeaz˘ a ¸ a a fi “consumat˘”. S-a cerut explicit functionarea a a ¸ unui serviciu web peste protocoale “prietenoase”. este necea s sar˘ o modalitate de a determina locatia serviciului .248 CURS 13. a a ¸ 13. a clientul va avea nevoie de o descriere a modului de interactiune cu SW. precum ¸i documentatie scris˘ despre SW continˆnd a s ¸ a ¸ a detalii sau exemple de utilizare. a 13. Faptul c˘ HTTP este f˘r˘ ıl a a aa stare permite crearea unor aplicatii care s˘ permit˘ continuarea servirii unor ¸ a a clienti chiar dac˘ serverul initial a c˘zut (sarcina sa fiind preluat˘ de alte ¸ a ¸ a a servere). XML este alegerea potrivit˘ pentru a¸a ceva.datele trimise ˆ ıntre cei 2 parteneri de conversatie trebuie ¸ codificate ˆ ıntr-un mod care s˘ permit˘ procesarea lor de c˘tre orice a a a limbaj.dac˘ se dore¸te conectarea la un serviciu Web. Acest lucru s permite abstractizarea protocoalelor de comunicare ¸i concentrarea pe s logica problemei.2.2. ˆ plus.modul prin care datele serializate care compun un mesaj sunt trimise de la un cap˘t la cel˘lalt. fiind structurat a s ¸i de tip text.

3 Conventia de formatare ¸ Al˘turi de corpul mesajului se transmit de cele mai multe ori ¸i metadate. DISCUTII ASUPRA BLOCURILOR COMPONENTE ¸ 249 Figura 13.1: Componentele unui serviciu Web ˆ acela¸i timp neutru din punct de vedere al platformei. ˆ acest fel dispar ın s In problemele legate de modul de reprezentare a datelor pe diverse arhitecturi de sisteme: textul poate fi procesat la fel de c˘tre oricine.13. a s Simple Object Access Protocol (SOAP) este un protocol care descrie regulile ¸i formatul pentru comunicare. exist˘ a In a o multitudine de parsere XML care pot fi utilizate chiar ¸i pe platforme cu s putere de procesare redus˘.org/soap/envelope/"> <soap:Body> <PurchaseOrder ID="3245"> . Prin intermediul lui SOAP se pot transmite s documente ¸i se pot face apeluri de metode: s <soap:Envelope xmlns:soap="http://schemas. a 13.2.2. ˆ plus.xmlsoap.

Pemite descrierea continutului t a ¸ mesajului dintre client ¸i serviciu.2. SERVICII WEB <From>Jim</From> <To>Frank</To> <Items> <Item ID="111">Dingbats</Item> <Item ID="222">Widgets</Item> </Items> </PurchaseOrder> </soap:Body> </soap:Envelope> ˆ exemplul de mai sus se transmite continutul unei comenzi de la Jim la In ¸ Frank.5 Mecanisme de descoperire Universal Description. Structura general˘ a unui mesaj SOAP este un “plic”1 care este format din a header-e (metadate asociate mesajului) ¸i continut propriu-zis. Discovery. s ¸ 13.xmlsoap.4 Mecanismul de descriere Web Services Description Language (WSDL) define¸te un document XML s care permite descrierea serviciului Web ¸int˘.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas. and Integration (UDDI) este mecansimul prin care se aduce la cuno¸tint˘ existenta unor servicii web disponibile s ¸a ¸ 1 Engl: envelope .xmlsoap. Pentru apelul unei metode la distant˘ s-ar putea folosi: ¸a <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.com/Stock"> <symbol>MSFT</symbol> </m:GetStockPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> corespunz˘tor apelului de metod˘ C#: a a GetStockPrice( "msft" ).2.250 CURS 13.org/soap/encoding/"> <SOAP-ENV:Body> <m:GetStockPrice xmlns:m="http://contoso. realizarea de tipuri de date utilizator. s formatul de comunicare ˆ ıntre client ¸i server. s 13.

Web. se creeaz˘ un fi¸ier cu extensia asmx ˆ acest director (fie el Test. 13. using System.3.3.1 Adunarea a dou˘ numere a Vom crea un serviciu Web care preia dou˘ numere ˆ a ıntregi ¸i returneaz˘ s a suma lor.org/">5</int> Descrierea pentru acest serviciu (documentul WSDL) este obtinut˘ prin ¸ a adresa: http://localhost/Test/Test. tipul de SW. UDDI este un director centralizat care poate fi folosit pentru a anuntarea de SW.asmx. compania.0" encoding="utf-8" ?> <int xmlns="http://tempuri.NET. s un format XML proprietar Microsoft. pentru care se poate face c˘utarea dup˘ criterii: cate¸ a a goria. public class TestClass { [WebMethod] public int Add( int a. avˆnd ca principal consumator Visual a Studio . etc. acest lucru se face prin crearea unui director virtual (de ex.13. 13. De asemenea se poate folosi ¸i DISCO.Services. .asmx) a s ın ¸i se scrie codul: s <%@ WebService Class="TestClass" Language="C#" %> using System. CREAREA UNUI SERVICIU WEB SIMPLU 251 oric˘rui client. Test). Manual. R˘spunsul este un document XML: a <?xml version="1.3 Crearea unui serviciu Web simplu Mai jos exemplific˘m crearea unui SW ¸i a unor clienti care s˘ interactioneze a s ¸ a ¸ cu acestea. int b) { return a+b. } } Drept client se poate folosi browser-ul IE cu adresa: http://localhost/Test/Test.asmx?WSDL.

ˆ partea de cod se a s ın In scrie metoda: [WebMethod] public bool ValidateCardNo(String cardNo.asmx. Din Solution a Explorer se modific˘ numele fi¸ierului ˆ PlataWS.2: Preluarea datelor unei c˘rti de credit a¸ Pentru a se putea accesa serviciul web.2 Validarea unui num˘r de card de credit a S˘ presupunem c˘ avem de implementat un site de tip B2C (de exemplu a a vˆnzare de c˘rti).NET Web Service->se completeaz˘ numele PlataWS. ˆ care s˘ se poat˘ introduce num˘rul de card ¸i data expir˘rii. se intr˘ ˆ Solution Explorer ¸i a ın s se adaug˘ la References un Web Reference la serviciul local PlataWS numit a . SERVICII WEB 13.252 CURS 13.Parse(cardNo) %2 == 0. Atunci cˆnd se efectueaz˘ plata prin card de credit se a a¸ a a cere de la utilizator num˘rul de card ¸i data expir˘rii. Se presupune c˘ a s a a aceast˘ validare nu este f˘cut˘ de c˘tre aplicatie. String date) { return int. ci pe baza unui serviciu a a a a ¸ Web specializat. pe baza parit˘¸ii num˘rului de card).3.2. ın a a a s a Figura 13. de¸i a s se poate folosi ¸i alt˘ modalitate. a at a Pentru partea de site se poate crea o form˘ windows de tipul celei din a figura 13. Vom exemplifica cele ce urmeaz˘ prin Visual Studio. s a Pentru Web Service se poate proceda astfel: File->New->Project->se alege ASP. } (o validare simpl˘.

Read(fileContent.OpenRead(name).ValidateCardNo(NrCarte.PlataWS validator = new localhost.Length). } else { Validitate.Close(). ˆ a a ın functie de care se afi¸eaz˘ sau nu eroare.Content = new byte[fileStream. Codul apelat pe server la ap˘sarea butonului a de submitere este: private void Button1_Click(object sender.3.Length].ToString())) { Validitate. CREAREA UNUI SERVICIU WEB SIMPLU 253 localhost.Content.Text = "Invalid". Calendar1. s Pentru SW se va scrie codul: [WebMethod] public FileContent GetFile(String name) { FileStream fileStream = File. FileContent fileContent = new FileContent(). if (!validator.SelectedDate. fileContent. } 2 Cu toate c˘ FTP este mai potrivit pentru a¸a ceva a s .Name = name.Visible = true.Text.3. } } unde Validitate este un Label invizibil de pe form˘. fileContent. fileStream.3 SW pentru transmitere de continut binar ¸ Folosind SOAP se poate transmite orice fel de mesaj.Visible = false. indiferent de sursa de provenient˘ a acestuia. Aceasta permite crearea unui obiect de tipul PlataWS pentru care se va apela metoda de validare.EventArgs e) { localhost.Content. Validitatea este deci a testat˘ prin intermediul unui serviciu Web care returneaz˘ true sau false.PlataWS(). ¸ s a 13. System. Vom ar˘ta mai jos modul ˆ care se poate face ¸a a ın transmiterea unui fi¸ier binar folosind servicii Web2 .13. fileStream. return fileContent. 0. Validitate. fileContent.

} } Aplicatia client poate s˘ fie de tip form˘ Windows.Write( fileContent.GetFile(textBox1. Deoarece un mesaj SOAP etse un document XML.XML. sw. pentru el se poate folosi orice fel de protocol care ¸tie s˘ transmit˘ text s a a • nu este legat de nici o infrastructur˘ distribuit˘ (DCOM. SERVICII WEB unde FileContent este o structur˘ definit˘ ˆ acela¸i spatu de nume: a a ın s ¸ namespace FileTransfer { public struct FileContent { public string Name. ce permite specificarea c˘ii ¸ a a a absolute a unui fi¸ier aflat pe server ¸i care salveaz˘ continutul obiectului de s s a ¸ tip FileTransfer pe discul local. 0.FileContent fileContent = transfer. fileContent.FileTransfer(). sw. Stream sw = File.254 CURS 13.4 SOAP SOAP (Simple Object Access Protocol) specific˘ modul de ˆ a ımpachetare a mesajelor. public byte[] Content. Secventa de cod pentru apelarea serviciului Web este: ¸ private void button1_Click(object sender. site. astfel ¸a a putˆnd-se referi orice tip de date declarat public ˆ interiorul spatiului de a ın ¸ nume.Length ).bin"). Pentru accesarea serviciului Web se adaug˘ a o referint˘ Web la serviciul creat anterior (denumit˘ mai jos site). etc) a a • se folose¸te de standarde existente . Corba.FileTransfer transfer = new site. Cˆteva avantaje ale SOAP-ului sunt: a • nu este puternic cuplat cu vreun limbaj de programare. System.OpenWrite(@"c:\temp\output.EventArgs e) { site. nu se specific˘ a un API. } 13.Content.Content.Text). HTTP. SMTP. SOAP se poate folosi din orice limbaj sau de pe orice platform˘ a • nu este legat de vreaun protocol de transport anume. XML schema.Close(). s etc .

dac˘ se folose¸te a a a a s un anumit algoritm de compresie a continutului mesajului atunci receptorul ¸ trebuie s˘ ¸tie care este acesta. <?xml version="1.4. Dar pentru o parte a acesora a se poate cere ca s˘ se asigure ˆ ¸elegerea unui anumit header s˘ fie garantat˘ a ınt a a ˆ de c˘tre client sau ca ˆ a ıntregul mesaj s˘ fie ignorat. dispozitive mobile.com</email> <firstName>Scott</firstName> <lastName>Short</lastName> </UpdateAccountInfo> </soap:Body> </soap:Envelope> . Intr-un asemenea caz se a specific˘ pentru acel element de header atributul mustUnderstand cu valoarea a 1. 13. mainframe-uri.xmlsoap.4.13. etc Un mesaj SOAP const˘ ˆ a ıntr-un plic compus ˆ principal din header-e ¸i ın s corp. SOAP 255 • interoperabilitate ˆ ıntre platforme: SOAP poate fi folosit de c˘tre PCa uri.dac˘ mesajul trebuie s˘ ajung˘ la mai multe ¸ a a a destinatii ¸ Atributul mustUnderstand Headerele pot fi ignorate de c˘tre receptor.1 Header-e Elementele de header sunt folosite pentru a transmite continut care nu ¸ are leg˘tur˘ propriu-zis˘ cu corpul mesajului. De exemplu. De asemenea se pot include: as • autentificare .org/soap/envelope/"> <soap:Header> <TransactionId soap:mustUnderstand="1">123</TransactionId> </soap:Header> <soap:Body> <UpdateAccountInfo> <email>sshort@microsoft.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.se poate cere receptorului s˘ se autentifice ˆ a ınainte de a fi procesat mesajul • informatie de tip rezumat sau semn˘tur˘ digital˘ pentru a se asigura ¸ a a a c˘ continutul mesajului nu afost alterat a ¸ • informatie de rutare .

s˘ presupunem c˘ SW cere apelarea unei metode de a a adunare a 2 numere: public int Add(int x. SERVICII WEB Un mesaj SOAP paote fi rutat prin mai multi intermediari. Se folose¸te ¸ s un atribut actor care specific˘ adresa intermediarului. dar poate s˘ a ¸ ıl s a adauge la rˆndul lui alt˘ informatie de acest tip.256 Atributul actor CURS 13. int y) { return x + y.0"?> <soap:Envelope xmlns:soap="http://schemas. } Mesajul SOAP la apelarea acestei metode este: <?xml version="1.org/soap/envelope/"> <soap:Body> <Add> <x>1</x> <y>2</y> </Add> </soap:Body> </soap:Envelope> R˘spunsul generat de serviciul Web este: a <?xml version="1.2 Elementul body Un mesaj SOAP poate avea un singur element de tip body al c˘rui a continut poate s˘ fie structurat XML sau simple ¸iruri de caractere. a a ¸ 13. Pe baza acesa ¸ ¸ a tui continut.0"?> <soap:Envelope xmlns:soap="http://schemas. Acest intermediar a trebuie s˘ elimine informatia de intermediar care ˆ prive¸te. orice ¸ a s care nu invalideaz˘ continutul documentului XML contin˘tor.xmlsoap.4. a Pentru primul caz.xmlsoap.org/soap/envelope/"> <soap:Body> <AddResult> <result>3</result> . un mesaj SOAP poate fi privit ca un mesaj orientat pe proce¸ dur˘ sau ca unul de tip document.

SOAP </AddResult> </soap:Body> </soap:Envelope> 257 Exist˘ suport pentru transmiterea tipurilor de date definite de utilizator. a a array-urilor. etc. a ¸a s grafurilor de obiecte.13. .4. definirea parametrilor ca fiind de tip valoare/referint˘/ie¸ire.

SERVICII WEB .258 CURS 13.

Thia Thuan. APress. 2002 [7] Professional ADO. Web Developer’s Guide. O’Reilly.NET Programming. Werry Jasson. Albahari Joseph. Octombrie 2002 [5] A Programmer’s Introduction to C#. Syngress Publishing. Lam Hoang Q. O’Reilly. Wrox. ECMA TC39/TG2. 2001 [4] C# Language Specification. Syngress Publishing. 2001 [3] .NET.com. 2002 [2] Programming C#. Hack Greg.NET Framework Essentials. DotThatCom. Nandu Saurabh.. Eric Gunnerson. 2001 [6] A Programmers’s Introduction to C#. 2001 259 . Lee Wei Meng. Jesse Liberty. Turtschi Adrian.Bibliografie [1] C# .

Sign up to vote on this title
UsefulNot useful