Documente Academic
Documente Profesional
Documente Cultură
Programarea
Orientatã
pe Obiecte
ºi
Programarea Vizualã
Microsoft ®
.NET
Framework
Cuprins
I. PROGRAMARE ORIENTAT PE OBIECTE.............................................................................................. 3
I.1. INTRODUCERE IN .NET.............................................................................................................................. 3
I.1.1. Arhitectura .NET Framework .......................................................................................................... 4
I.1.2. Compilarea programelor................................................................................................................. 4
I.1.3. De ce am alege .NET? ..................................................................................................................... 5
I.2. INTRODUCERE ÎN LIMBAJUL C# ................................................................................................................. 5
I.2.1. Caracterizare................................................................................................................................... 5
I.2.2. Crearea aplica iilor consol ............................................................................................................ 6
I.2.3. Structura unui program C#.............................................................................................................. 8
I.2.4. Sintaxa limbajului.......................................................................................................................... 10
I.2.4.6. Expresii i operatori ......................................................................................................................... 12
I.2.6.9. Instruc iunile try-catch-finally i throw............................................................................................ 48
I.3. PRINCIPIILE PROGRAM RII ORIENTATE PE OBIECTE ................................................................................. 75
I.3.1. Evolu ia tehnicilor de programare ................................................................................................ 75
I.3.2. Tipuri de date obiectuale. Încapsulare .......................................................................................... 76
I.3.3. Supraînc rcare .............................................................................................................................. 78
I.3.4. Mo tenire ....................................................................................................................................... 79
I.3.5. Polimorfism. Metode virtuale ........................................................................................................ 80
I.3.6. Principiile program rii orientate pe obiecte ................................................................................. 81
I.4. STRUCTURA UNEI APLICA II ORIENTAT PE OBIECTE ÎN C#..................................................................... 81
I.4.1. Clas de baz i clase derivate...................................................................................................... 82
I.4.2. Constructori................................................................................................................................... 82
I.4.3. Supraînc rcarea constructorilor i definirea constructorilor în clasele derivate ......................... 83
I.4.4. Destructor...................................................................................................................................... 84
I.4.5. Metode ........................................................................................................................................... 84
I.5. CLASE I OBIECTE ................................................................................................................................... 88
I.5.1. Clase .............................................................................................................................................. 88
I.6. CLASE I FUNC II GENERICE .................................................................................................................. 111
I.7. DERIVAREA CLASELOR (MO TENIRE) .................................................................................................... 114
I.7.1. Principiile mo tenirii ................................................................................................................... 114
I.7.2. Accesibilitatea membrilor mo teni i ............................................................................................ 116
I.7.3. Metode ......................................................................................................................................... 118
I.7.4. Interfe e........................................................................................................................................ 119
I.8. TRATAREA EXCEP IILOR ÎN C#.............................................................................................................. 121
I.8.1. Aruncarea i prinderea excep iilor.............................................................................................. 123
I.9. POLIMORFISM ........................................................................................................................................ 126
I.9.1. Introducere .................................................................................................................................. 126
I.9.2. Polimorfismul parametric............................................................................................................ 127
I.9.3. Polimorfismul ad-hoc .................................................................................................................. 128
I.9.4. Polimorfismul de mo tenire ......................................................................................................... 129
I.9.5. Modificatorii virtual i overide ......................................................................................... 130
I.9.6. Modificatorul new ....................................................................................................................... 131
I.9.7. Metoda sealed.......................................................................................................................... 132
II. PROGRAMARE VIZUAL ....................................................................................................................... 133
I....................................................................................................................................................................... 133
II ..................................................................................................................................................................... 133
II.1. CONCEPTE DE BAZ ALE PROGRAM RII VIZUALE.............................................................................. 133
II.2. MEDIUL DE DEZVOLTARE VISUAL C# (PREZENTAREA INTERFE EI) .................................................. 134
II.3. ELEMENTELE POO ÎN CONTEXT VIZUAL ........................................................................................... 136
Barele de instrumente ................................................................................................................................. 138
II.4. CONSTRUIREA INTERFE EI UTILIZATOR ............................................................................................ 143
II.4.1. Ferestre........................................................................................................................................ 143
II.4.2. Controale ..................................................................................................................................... 146
II.5. APLICA II ......................................................................................................................................... 147
II.5.1. Numere pare ................................................................................................................................ 147
II.5.2. Propriet i comune ale controalelor i formularelor: ................................................................. 149
II.5.3. Metode i evenimente................................................................................................................... 150
1
II.5.4. Obiecte grafice............................................................................................................................. 172
II.5.5. Validarea informa iilor de la utilizator ....................................................................................... 174
II.5.6. MessageBox ................................................................................................................................. 175
II.5.7. Interfa definit de c tre utilizator............................................................................................ 178
II.5.8. Browser creat de c tre utilizator ................................................................................................. 186
II.5.9. Ceas ............................................................................................................................................. 191
II.6. ACCESAREA I PRELUCRAREA DATELOR PRIN INTERMEDIUL SQL SERVER ....................................... 194
II.6.1. Crearea unei baze de date. Conectare i deconectare................................................................. 194
II.6.2. Popularea bazei de date .............................................................................................................. 196
II.6.3. Introducere în limbajul SQL ........................................................................................................ 197
II.7. ACCESAREA I PRELUCRAREA DATELOR CU AJUTORUL MEDIULUI VIZUAL........................................ 205
II.7.1. Conectare i deconectare............................................................................................................. 205
II.7.2. Opera ii specifice prelucr rii tabelelor ....................................................................................... 208
II.8. ACCESAREA I PRELUCRAREA DATELOR CU AJUTORUL ADO.NET................................................... 209
II.8.1. Arhitectura ADO.NET ................................................................................................................. 210
II.8.2. Furnizori de date (Data Providers) ............................................................................................. 211
II.8.3. Conectare..................................................................................................................................... 211
II.8.4. Comenzi ....................................................................................................................................... 213
II.8.5. DataReader.................................................................................................................................. 213
II.8.6. Constructori i metode asociate obiectelor de tip comand ........................................................ 215
II.8.7. Interogarea datelor...................................................................................................................... 218
II.8.8. Inserarea datelor ......................................................................................................................... 218
II.8.9. Actualizarea datelor .................................................................................................................... 219
II.8.10. tergerea datelor ........................................................................................................................ 220
II.8.11. DataAdapter i DataSet .............................................................................................................. 223
II.9. APLICA IE FINAL ............................................................................................................................ 226
2
I. Programare orientat pe obiecte
.NET este un cadru (Framework) de dezvoltare software unitar care permite realizarea,
distribuirea i rularea aplica iilor desktop Windows i aplica iilor WEB.
Tehnologia .NET pune laolalt mai multe tehnologii (ASP, XML, OOP, SOAP, WDSL, UDDI)
i limbaje de programare (VB, C++, C#, J#) asigurând, totodat , atât portabilitatea codului compilat
între diferite calculatoare cu sistem Windows, cât i reutilizarea codului în programe, indiferent de
limbajul de programare utilizat.
.NET Framework este o component livrat împreun cu sistemul de operare Windows. De
fapt, .NET 2.0 vine cu Windows Server 2003, se poate instala pe versiunile anterioare, pân la
Windows 98 inclusiv; .NET 3.0 vine instalat pe Windows Vista i poate fi instalat pe versiunile
Windows XP cu SP2 i Windows Server 2003 cu minimum SP1.
Pentru a dezvolta aplica ii pe platforma .NET este bine s avem 3 componente esen iale:
un set de limbaje (C#, Visual Basic .NET, J#, Managed C++, Smalltalk, Perl, Fortran,
Cobol, Lisp, Pascal etc),
un set de medii de dezvoltare (Visual Studio .NET, Visio),
o bibliotec de clase pentru crearea serviciilor Web, aplica iilor Web i aplica iilor desktop
Windows.
Când dezvolt m aplica ii .NET, putem utiliza:
Servere specializate - un set de servere Enterprise .NET (din familia SQL Server 2000,
Exchange 2000 etc), care pun la dispozi ie func ii de stocare a bazelor de date, email,
aplica ii B2B (Bussiness to Bussiness – comer electronic între partenerii unei afaceri).
Servicii Web (în special comerciale), utile în aplica ii care necesit identificarea
utilizatorilor (de exemplu, .NET Passport - un mod de autentificare folosind un singur
nume i o parol pentru toate site-urile vizitate)
Servicii incluse pentru dispozitive non-PC (Pocket PC Phone Edition, Smartphone, Tablet
PC, Smart Display, XBox, set-top boxes, etc.)
.NET Framework
Componenta .NET Framework st la baza tehnologiei .NET, este ultima interfa între
aplica iile .NET i sistemul de operare i actualmente con ine:
Limbajele C#, VB.NET, C++ i J#. Pentru a fi integrate în platforma .NET, toate aceste
limbaje respect ni te specifica ii OOP numite Common Type System (CTS). Ele au ca
elemente de baz : clase, interfe e, deleg ri, tipuri valoare i referin , iar ca mecanisme:
mo tenire, polimorfism i tratarea excep iilor.
3
Platforma comun de executare a programelor numit Common Language Runtime
(CLR), utilizat de toate cele 4 limbaje. CTS face parte din CLR.
Ansamblul de biblioteci necesare în realizarea aplica iilor desktop sau Web, numit
Framework Class Library (FCL).
FCL
Framework Base Classes
(IO, securitate, fire de execu ie, colec ii etc.)
CLR
Common Language Runtime
(execep ii, valid ri de tipuri,compilatoare JIT)
Componenta .NET Framework este format din compilatoare, biblioteci i alte executabile utile
în rularea aplica iilor .NET. Fi ierele corespunz toare se afl , în general, în directorul
C:\WINDOWS\Microsoft. NET\Framework\V2.0…. (corespunz tor versiunii instalate)
Un program scris într-unul dintre limbajele .NET conform Common Language Specification
(CLS) este compilat în Microsoft Intermediate Language (MSIL sau IL). Codul astfel ob inut are
extensia "exe", dar nu este direct executabil, ci respect formatul unic MSIL.
CLR include o ma in virtual asem n toare cu o ma in Java, ce execut instruc iunile IL
rezultate în urma compil rii. Ma ina folose te un compilator special JIT (Just In Time).
Compilatorul JIT analizeaz codul IL corespunz tor apelului unei metode i produce codul ma in
adecvat i eficient. El recunoa te secven ele de cod pentru care s-a ob inut deja codul ma in
adecvat, permi ând reutilizarea acestuia f r recompilare, ceea ce face ca, pe parcursul rul rii,
aplica iile .NET s fie din ce în ce mai rapide.
Faptul c programul IL produs de diferitele limbaje este foarte asem n tor are ca rezultat
interoperabilitatea între aceste limbaje. Astfel, clasele i obiectele create într-un limbaj specific
.NET pot fi utilizate cu succes în altul.
4
În plus, CLR se ocup de gestionarea automat a memoriei (un mecanism implementat în
platforma .NET fiind acela de eliberare automat a zonelor de memorie asociate unor date
devenite inutile – Garbage Collection).
Ca un element de portabilitate, trebuie spus c .NET Framework este implementarea unui
standard numit Common Language Infrastructure
(http://www.ecma-international.org/publications/standards/Ecma-335.htm ),
ceea ce permite rularea aplica iilor .NET, în afar de Windows, i pe unele tipuri de Unix, Linux,
Solaris, Mac OS X i alte sisteme de operare (http://www.mono-project.com/Main_Page ).
În primul rând pentru c ne ofer instrumente pe care le putem folosi i în alte programe,
ofer acces u or la baze de date, permite realizarea desenelor sau a altor elemente grafice.
Spa iul de nume System.Windows.Forms con ine instrumente (controale) ce permit implementarea
elementelor interfe ei grafice cu utilizatorul. Folosind aceste controale, pute i proiecta i dezvolta
rapid i interactiv, elementele interfe ei grafice. Tot .NET v ofer clase care efectueaz
majoritatea sarcinilor uzuale cu care se confrunt programele i care plictisesc i fur timpul
programatorilor, reducând astfel timpul necesar dezvolt rii aplica iilor.
I.2.1. Caracterizare
5
direct la memorie folosind pointeri) au fost p strate, dar secven ele de cod corespunz toare se
consider „nesigure”.
Pentru a realiza aplica ii consol (ca i cele din Borland Pascal sau Borland C) în mediul de
dezvoltare Visual Studio, trebuie s instal m o versiune a acestuia, eventual mediul free Microsoft
Visual C# 2008 Express Edition de la adresa http://www.microsoft.com/express/download/
Dup lansarea aplica iei, din meniul File se alege op iunea NewProject apoi alegem
ConsoleApplication, modificând numele aplica iei în caseta Name.
Când crea i o aplica ie consol , se genereaz un fi ier cu extensia .cs. În cazul nostru, s-a
generat fi ierul Primul.cs. Extensia cs provine de la C Sharp. Redenumirea lui se poate realiza
6
din fereastra Solution Explorer, pe care o pute i afi a cu ajutorul combina iei de taste Ctrl+W,S
sau din meniul View.
Codul surs generat este :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{ class Program
{
static void Main(string[] args)
{
}
}
}
Console.WriteLine("Primul program");
Pentru compilarea programului, selecta i Build din meniul principal sau ap sa i tasta F6. În
cazul în care ave i erori, acestea sunt afi ate în fereastra Error List. Efectuând dublu-clic pe
fiecare eroare în parte, cursorul din program se pozi ioneaz pe linia con inând eroarea.
Rularea programului se poate realiza în mai multe moduri:
rapid f r asisten de depanare (Start Without Debugging Ctrl+F5)
7
Icoanele din IntelliSense i semnifica ia lor
1 using System;
2
3 namespace HelloWorld
4 {
5 class Program
6 {
7 static void Main()
8 {
9 Console.WriteLine("Hello World!");
10 }
11 }
12 }
O aplica ie C# este format din una sau mai multe clase, grupate în spa ii de nume
(namespaces). Este obligatoriu ca doar una din aceste clase s con in un „punct de intrare”
(entry point), i anume metoda (func ia) Main.
8
Clasa (class), în termeni simplifica i, reprezint principalul element structural i de
organizare în limbajele orientate spre obiecte, grupând date cât i func ii care prelucreaz
respectivele date.
Spa iul de nume (Namespaces): din ra iuni practice, programele mari, sunt divizate în
module, dezvoltate separat, de mai multe persoane. Din acest motiv, exist posibilitatea de a
ap rea identificatori cu acela i nume. Pentru a evita erori furnizate din acest motiv, în 1955
limbajul C++ introduce no iunea i cuvântul cheie namespace. Fiecare mul ime de defini ii dintr-o
libr rie sau program este grupat într-un spa iu de nume, existând astfel posibilitatea de a avea
într-un program defini ii cu nume identic, dar situate în alte spa ii de nume. În cazul în care, într-o
aplica ie, unele clase sunt deja definite, ele se pot folosi importând spa iile de nume care con in
defini iile acestora. Mai men ion m faptul c un spa iu de nume poate con ine mai multe spa ii de
nume.
9
I.2.4. Sintaxa limbajului
Ca i limbajul C++ cu care se înrude te, limbajul C# are un alfabet format din litere mari i
mici ale alfabetului englez, cifre i alte semne. Vocabularul limbajului este format din acele
„simboluri” cu semnifica ii lexicale în scrierea programelor: cuvinte (nume), expresii, separatori,
delimitatori i comentarii.
I.2.4.1. Comentarii
comentariu pe mai multe rânduri prin folosirea /* i */. Orice text cuprins între
simbolurile men ionate mai sus se consider a fi comentariu. Simbolurile /* reprezint
începutul comentariului, iar */ sfâr itul respectivului comentariu.
/* Acesta este un
comentariu care se
intinde pe mai multe randuri */
I.2.4.2. Nume
Defini ie: Prin nume dat unei variabile, clase, metode etc. în elegem o succesiune de
caractere care îndepline te urm toarele reguli:
numele trebuie s înceap cu o liter sau cu unul dintre caracterele ”_” i ”@”;
primul caracter poate fi urmat numai de litere, cifre sau un caracter de subliniere;
numele care reprezint cuvinte cheie nu pot fi folosite în alt scop decât acela pentru care
au fost definite;
cuvintele cheie pot fi folosite în alt scop numai dac sunt precedate de @;
10
dou nume sunt distincte dac difer prin cel pu in un caracter (fie el i liter mic ce
difer de aceea i liter majuscul ).
11
I.2.4.3. Constante
Exemplul 1:
Constantele declarate cu ajutorul lui readonly sunt doar variabilele membre ale claselor,
ele putând fi ini ializate doar de c tre constructorii claselor respective.
Exemplul 2:
I.2.4.4. Variabile
O variabil în C# poate s con in fie o valoare a unui tip elementar, fie o referin la un
obiect. C# este „case sensitive”, deci face distinc ie între litere mari i mici.
Exemplul 3:
int Salut;
int Azi_si_maine;
char caracter;
Defini ie: Prin expresie se în elege o secven format din operatori i operanzi. Un
operator este un simbol ce indic ac iunea care se efectueaz , iar operandul este valoarea
asupra c reia se execut opera ia.
Operatorii se împart în trei categorii:
12
Unari: - ac ioneaz asupra unui singur operand
Binari: - ac ioneaz între doi operanzi
Ternari: - ac ioneaz asupra a trei operanzi; exist un singur operator ternar i acesta
este ?:
În C# sunt defini i mai mul i operatori. În cazul în care într-o expresie nu intervin paranteze,
opera iile se execut conform priorit ii operatorilor. În cazul în care sunt mai mul i operatori cu
aceea i prioritate, evaluarea expresiei se realizeaz de la stânga la dreapta. În tabelul al turat
prioritatea descre te de la 0 la 13.
Tabelul de priorit i:
Exemplul 4: folosind operatorul ternar ?:, s se decid dac un num r citit de la tastatur este
pozitiv sau negativ.
Indica ii:
Sintaxa acestui operator este: (condi ie) ? (expr_1): (expr_2) cu semnifica ia se evalueaz
condi ie, dac ea este adev rat se execut expr_1, altfel expr_2
int.Parse converte te un ir la int
13
using System;
using System.Collections.Generic;
using System.Text;
namespace OperatorConditional
{ class Program
{
static void Main(string[] args)
{ int a;
string rezultat;
a = int.Parse(Console.ReadLine());
Console.Write(a);
rezultat = (a > 0) ? " este nr. pozitiv" : " este nr. negativ";
Console.Write(rezultat);
Console.ReadLine();
}
}
}
Exemplul 5: Folosind operatorul %, s se verifice dac un num r este par sau impar. Observa ie:
Convert.ToInt32 converte te un ir la Int32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace primul_proiect
{ class Program
{ static void Main(string[] args)
{
int x;
x = Convert.ToInt32(Console.ReadLine());
if (x % 2 == 0) Console.WriteLine("este par");
else System.Console.WriteLine("este impar");
}
}
}
14
Exemplul 6: Urm torul program afi eaz la consol tabelul de adev r pentru operatorul logic &.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_6
{
class Program
{
static void Main(string[] args)
{
bool v1, v2;
v1 = true; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = true; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = false; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = false; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
Console.ReadKey();
}
}
}
Pentru a avea control asupra modului de afi are a informa iei numerice, se poate folosi
urm toarea form a lui WriteLine():
WriteLine("sir",var1,var2,…, varn);
15
specificatorii de format ce au forma general {nr_var,width:fmt} unde nr_var
precizeaz num rul variabilei (parametrului) care trebuie afi at începând cu 0, width
stabile te l imea câmpului de afi are, iar fmt stabile te formatul
Exemplul 7:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_7
{
class Program
{
static void Main(string[] args)
{
int a, b, c = 5;
a = c++;
b = ++c;
Console.WriteLine("a={0} b={1}", a,b);
}
}
}
Exemplul 8: în acest exemplu, formatul de afi are ales #.### va produce afi area cu trei
zecimale a constantei PI
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_8
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Valoarea constantei matematice PI este
{0:#.###}",Math.PI);
}
}
}
16
I.2.4.8. Conversii
Exemplul 9: Exemplul urm tor realizeaz suma a dou valori numerice f r semn cu reprezentare
pe 8 bi i. Rezultatul va fi re inut pe 64 bi i
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_9
{
class Program
{
static void Main(string[] args)
{
byte a = 13; // byte intreg fara semn pe 8 bi i
byte b = 20;
long c; // intreg cu semn pe 64 bi i
c = a + b;
Console.WriteLine("{0} + {1} = {2}", a, b, c);
Console.WriteLine("Suma intregilor pe 8 bi i se reprezinta pe 64
bi i");
}
}
}
17
I.2.4.8.1. Conversiile implicite
Regula dup care se efectueaz conversiile implicite este descris de tabelul urm tor:
din în
sbyte short, int, long, float, double, decimal
byte short, ushort, int, uint, long, ulong, float, double, decimal
short int, long, float, double, decimal
ushort int, uint, long, ulong, float, double, decimal
int long, float, double, decimal
uint long, ulong, float, double, decimal
long float, double, decimal
char ushort, int, uint, long, ulong, float, double, decimal
float double
ulong float, double, decimal
Se realizeaz prin intermediul unei expresii cast (care va fi studiat mai târziu), atunci când
nu exist posibilitatea unei conversii implicite.
din în
sbyte byte, ushort, uint, ulong, char
byte sbyte, char
short sbyte, byte, ushort, uint, ulong, char
ushort sbyte, byte, short, char
int sbyte, byte, short, ushort, uint, ulong, char
uint sbyte,byte, short, ushort, int, char
long sbyte, byte, short, ushort, int, uint, ulong, char
ulong sbyte, byte, short, ushort, int, uint, long, char
char sbyte, byte, short
float sbyte, byte, short, ushort, int, uint, long, ulong, char, decimal
double sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
decimal
decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double
18
Exemplul 10:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_10
{
class Program
{
static void Main(string[] args)
{
int a = 5;
int b = 2;
float c;
c = (float)a / b; //operatorul cast
Console.WriteLine("{0} / {1} = {2}", a, b, c);
Console.WriteLine("Catul intregilor, reprezentat ca real datorita
operatorului cast\nde conversie explicita");
}
}
}
În cazul în care nu s-ar fi folosit operatorul cast, rezultatul - evident eronat - ar fi fost:
Des întâlnit este conversia din tipul numeric în ir de caractere i reciproc. Conversia din
tipul numeric în ir de caractere se realizeaz cu metoda ToString a clasei Object
Exemplul 11:
int i = 13
string j = i.ToString();
19
Conversia din ir de caractere în num r se realizeaz cu ajutorul metodei Parse tot din
clasa Object.
Exemplul 12:
string s = "13";
int n = int.Parse(s);
Exemplul 13: Exemplul de mai jos prezint mai multe tipuri de conversii
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_13
{
class Program
{
static void Main(string[] args)
{
short srez, sv = 13;
int iv = 123;
long lrez;
float frez, fv = 13.47F;
double drez, dv = 87.86;
string strrez, strv = "15";
bool bv = false;
Console.WriteLine("Exemple de conversii:\n");
Console.WriteLine("Implicite:");
drez = fv + sv;
Console.WriteLine("float si short spre double {0} + {1} = {2}",
fv, sv, drez);
frez = iv + sv;
Console.WriteLine("int si short spre float {0} + {1} = {2}\n",
iv, sv, frez);
Console.WriteLine("Explicite:");
srez = (short)fv;
Console.WriteLine("float spre short folosind cast {0} spre {1}",
fv, srez);
lrez = iv + Convert.ToInt64(strv);
Console.WriteLine("int si string cu ToInt64 spre long {0} + {1} =
{2}", iv, strv, lrez);
}
}
}
20
I.2.4.8.3. Conversii boxing i unboxing
Datorit faptului c în C# toate tipurile sunt derivate din clasa Object (System.Object),
prin conversiile boxing (împachetare) i unboxing (despachetare) este permis tratarea tipurilor
valoare drept obiecte i reciproc. Prin conversia boxing a unui tip valoare, care se p streaz pe
stiv , se produce ambalarea în interiorul unei instan e de tip referin , care se p streaz în
memoria heap, la clasa Object. Unboxing permite convertirea unui obiect în tipul valoare
echivalent.
Exemplul 14:
sau
int i = 13;
object ob = i; //boxing implicit
21
Se poate determina tipul pentru care s-a f cut împachetarea folosind operatorul is:
Exemplul 15:
int i = 13;
object ob = i;
if (ob is int)
{
Console.WriteLine("Impachetarea s-a facut pentru int");
}
Exemplul 16:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{class Program
{static void Main(string[] args)
{
int i = 13;
object ob = i;
i=6;
Console.WriteLine("In ob se pastreaza {0}", ob);
Console.WriteLine("Valoarea actuala a lui i este {0}", i);
Console.ReadLine();
}
}
}
Exemplul 17: Prin conversia de tip unboxing, obiectul ob poate fi asignat variabilei întregi i:
int i = 13;
object ob = i; //boxing implicit
i = (int)ob; //unboxing explicit
22
I.2.4.8.4. Conversii între numere i iruri de caractere
Limbajul C# ofer posibilitatea efectu rii de conversii între numere i iruri de caractere.
Sintaxa pentru conversia num r în ir de caractere:
num r ir “” + num r
Observa ie: În cazul în care irul de caractere nu reprezint un num r valid, conversia
acestui ir la num r va e ua.
Exemplul 18:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_18
{
class Program
{
static void Main(string[] args)
{
string s;
const int a = 13;
const long b = 100000;
const float c = 2.15F;
double d = 3.1415;
Console.WriteLine("CONVERSII\n");
Console.WriteLine("TIP\tVAL. \tSTRING");
Console.WriteLine("----------------------");
s = "" + a;
Console.WriteLine("int\t{0} \t{1}", a, s);
s = "" + b;
Console.WriteLine("long\t{0} \t{1}", b, s);
s = "" + c;
Console.WriteLine("float\t{0} \t{1}", c, s);
s = "" + d;
Console.WriteLine("double\t{0} \t{1}", d, s);
Console.WriteLine("\nSTRING\tVAL \tTIP");
Console.WriteLine("----------------------");
int a1;
a1 = int.Parse("13");
23
Console.WriteLine("{0}\t{1}\tint", "13", a1);
long b2;
b2 = long.Parse("1000");
Console.WriteLine("{0}\t{1} \tlong", "1000", b2);
float c2;
c2 = float.Parse("2,15");
Console.WriteLine("{0}\t{1} \tfloat", "2,15", c2);
double d2;
d2 = double.Parse("3.1415",
System.Globalization.CultureInfo.InvariantCulture);
Exemplul 19:
using System;
using System.Collections.Generic;
using System.Text;
namespace ExempluTipuriValoare
{
public struct Intreg
{
public int v;
}
class Program
{
static void Main(string[] args)
{
Intreg sa = new Intreg();
sa.v = 13;
Intreg sb = sa;
// se initializeaza prin copiere variabila sb
Console.WriteLine("sa.v este {0}.", sa.v);
Console.WriteLine("sb.v este {0} prin initializare.", sb.v);
sa.v = 10;
Console.WriteLine("sa.v este {0}.", sa.v);
Console.WriteLine("sb.v este {0}.", sb.v);
Console.ReadLine();
}
}
}
Spre deosebire de tipurile valoare, pentru tipurile referin , declararea unei variabile nu
implic automat alocarea de spa iu: ini ial, referin ele sunt null i trebuie alocat explicit
memorie pentru obiectele propriu-zise. În plus, la atribuire, este copiat referin a în variabila
25
destina ie, dar obiectul spre care indic r mâne acela i (aliasing). Aceste reguli poarta
denumirea de reference semantics.
Exemplul 20: Pentru exemplificarea celor de mai sus, pentru tipurile referin , vom folosi clasa
StringBuilder.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ExempluTipuriReferinta
{
class Program
{
static void Main(string[] args)
{
StringBuilder a = new StringBuilder();
StringBuilder b = a;
a.Append("Salut");
Console.WriteLine("a este '{0}'.", a);
Console.WriteLine("b este '{0}' prin initializare.", b);
a = null;
Console.WriteLine("a este '{0}' prin atribuirea unei noi
valori.", a);
Console.WriteLine("b este '{0}'.", b);
Console.ReadLine();
}
}
}
Limbajul C# con ine un set de tipuri predefinite (int, bool etc.) i permite definirea unor
tipuri proprii (enum, struct, class etc.).
26
Tipuri simple predefinite
Sufix Tip
nu are int, uint, long, ulong
u, U uint, ulong
L, L long, ulong
ul, lu, Ul, lU, UL, LU, Lu ulong
27
Exemplul 21:
Tipul enumerare, asem n tor cu cel din C++, se define te de c tre utilizator. Acest tip
permite utilizarea numelor care, sunt asociate unor valori numerice.
Enumer rile nu pot fi declarate abstracte i nu pot fi derivate. Orice enum este derivat
automat din clasa System.Enum, derivat din System.ValueType.
În cazul în care nu se specific tipul enumer rii, acesta este considerat implicit int.
Specificarea tipului se face dup numele enumer rii:
Asem n tor celor cunoscute din C++, tipul structur poate s con in declara ii de constante,
câmpuri, metode, propriet i, indexatori, operatori, constructori sau tipuri imbricate.
28
Exemplul 22:
using System;
namespace tipulEnum
{class Program
{ enum lunaAnului
{ Ianuarie = 1,
Februarie,
Martie,
Aprilie,
Mai,
Iunie,
Iulie,
August,
Septembrie,
Octombrie,
Noiembrie,
Decembrie
}
static void Main(string[] args)
{
Console.WriteLine("Luna Mai este a {0}",(int)lunaAnului.Mai + "
luna din an.");
Console.ReadLine();
}
}
}
Tipurile nulabile, nullable, sunt tipuri valoare pentru care se pot memora valori posibile din
aria tipurilor de baz , eventual i valoarea null.
Am v zut mai sus c pentru tipurile valoare, la declararea unei variabile, aceasta
con ine valoarea implicit a tipului. Sunt cazuri în care se dore te ca, la declarare, valoarea
implicit a variabilei s fie nedefinit .
În C# exist o astfel de posibilitate, folosind structura System.Nullable<T>.
Concret, o declara ie de forma:
System.Nullable<T> var;
este echivalent cu
T? var;
unde T este un tip valoare.
29
Aceste tipuri nulabile con in dou propriet i:
proprietate HasValue, care indic dac valoarea intern este diferit sau nu de null
proprietatea Value, care va con ine valoarea propriu zis .
Legat de aceast no iune, s-a mai introdus operatorul binar ??
a ?? b
cu semnifica ia: dac a este null b este evaluat i constituie rezultatul expresiei, altfel
rezultatul este a.
Ne referim aici la instruc iunile construite folosind cuvintele cheie: if, else, do, while,
switch, case, default, for, foreach, in, break, continue, goto.
I.2.6.1. Instruc iunea if
Instruc iunea if are sintaxa:
if (conditie)
Instructiuni_A;
else
Instructiuni_B;
Exemplul 23: Citindu-se dou numere întregi, s se decid care dintre ele este mai mare
using System;
namespace Exemplul_23
{
class Program
{
static void Main(string[] args)
{
int a, b;
string rezultat;
Console.Write("Dati primul numar intreg : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati al doilea numar intreg : ");
b = Convert.ToInt32(Console.ReadLine());
if (a > b) rezultat = "primul este mai mare";
else
if (a < b) rezultat = "primul este mai mic";
else rezultat = "numere egale";
Console.WriteLine("Rezultatul comparatiei lui {0} cu {1} este
\"{2}\"", a, b, rezultat);
}
}
}
30
Exemplul 24: S se verifice dac 3 puncte din plan M1, M2 i M3, date prin coordonatele lor întregi,
sunt coliniare.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_24
{
class Program
{
static void Main(string[] args)
{
double x1, y1, x2, y2, x3, y3;
Console.WriteLine("Coordonatele primului punct:");
Console.Write("Abscisa : ");
x1 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y1 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al doilea punct:");
Console.Write("Abscisa : ");
x2 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y2 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al treilea punct:");
Console.Write("Abscisa : ");
x3 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y3 = Convert.ToDouble(System.Console.ReadLine());
if (E == 0) Console.WriteLine("Puncte coliniare");
else Console.WriteLine("Puncte necoliniare");
}
}
}
31
Exemplul 25: S se verifice dac un num r întreg x este într-un interval dat [a, b]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_25
{
class Program
{
static void Main(string[] args)
{
int a, b, x;
Console.WriteLine("Se citesc doua numere care vor reprezenta
capetele intervalului");
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
if (a > b)
{
x = a;
a = b;
b = x;
} // interschimbarea valorilor pentru a avea intervalul [a, b]
Console.Write("x = ");
x = Convert.ToInt32(Console.ReadLine());
if (x >= a && x <= b)
Console.WriteLine("Numarul {0} este in intervalul [ {1}, {2}
]", x, a, b);
else
Console.WriteLine("Numarul {0} nu este in intervalul [ {1},
{2} ]", x, a, b);
}
}
}
32
I.2.6.2. Instruc iunea switch
În cazul instruc iunii switch în C/C++, dac la finalul instruc iunilor dintr-o ramur case nu
exist break, se trece la urm torul case. În C# se semnaleaz eroare. Exist i aici posibilitatea
de a face verific ri multiple (în sensul de a trece la verificarea urm toarei condi ii din case) doar
dac case-ul nu con ine instruc iuni:
Instruc iunea switch admite în C# variabil de tip ir de caractere care s fie comparat cu
irurile de caractere din case-uri:
Exemplul 26: Programul urm tor afi eaz ultima cifr a num rului xn, unde x i n sunt numere
naturale citite de la tastatur .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_26
{
class Program
{
static void Main(string[] args)
{
int x, n, k, ux;
Console.Write("Dati un numar natural ca baza a puterii : ");
x = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati un numar natural ca exponent al puterii : ");
n = Convert.ToInt32(Console.ReadLine());
if (n == 0) Console.WriteLine(" 1 ");
else
switch (ux)
{
case 0: Console.WriteLine(" 0 "); break;
case 1: Console.WriteLine(" 1 "); break;
case 2:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 "); break;
case 1: Console.WriteLine(" 2 "); break;
case 2: Console.WriteLine(" 4 "); break;
case 3: Console.WriteLine(" 8 "); break;
}
break;
33
case 3:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 "); break;
case 1: Console.WriteLine(" 3 "); break;
case 2: Console.WriteLine(" 9 "); break;
case 3: Console.WriteLine(" 7 "); break;
}
break;
case 4:
if (n % 2 == 0) Console.WriteLine(" 6 ");
else Console.WriteLine(" 4 ");
break;
case 5:
Console.WriteLine(" 5 ");
break;
case 6:
Console.WriteLine(" 6 ");
break;
case 7:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 "); break;
case 1: Console.WriteLine(" 7 "); break;
case 2: Console.WriteLine(" 9 "); break;
case 3: Console.WriteLine(" 3 "); break;
}
break;
case 8:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 "); break;
case 1: Console.WriteLine(" 8 "); break;
case 2: Console.WriteLine(" 4 "); break;
case 3: Console.WriteLine(" 2 "); break;
}
break;
case 9:
if (n % 2 == 0) Console.WriteLine(" 1 ");
else Console.WriteLine(" 9 ");
break;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
34
Exemplul 27: Programul urm tor efectueaz calculele corespunz toare pentru dou numere întregi
i unul dintre semnele +,-,*,/ , % introduse de la tastatur
namespace Exemplul_27
{
class Program
{
static void Main(string[] args)
{
char op;
int a, b;
Console.WriteLine("Exemplu pentru operatori aritmetici");
Console.Write("Dati primul numar intreg : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati al doilea numar intreg : ");
b = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati simbolul unui operator aritmetic : ");
op = (char)Console.Read();
switch (op)
{
case '+': Console.WriteLine("Adunare : {0} + {1} = {2}", a,
b, a + b);
break;
case '-': Console.WriteLine("Scadere : {0} - {1} = {2}", a,
b, a - b);
break;
case '*': Console.WriteLine("Inmultire : {0} * {1} = {2}", a,
b, a * b);
break;
case '/': Console.WriteLine("Impartire : {0} / {1} = {2}", a,
b, (float)a / b);
break;
case '%': Console.WriteLine("Modulo : {0} % {1} = {2}", a,
b, a % b);
break;
default: Console.WriteLine("Simbolul nu reprezinta o operatie
aritmetica");
break;
}
}
}
}
35
I.2.6.2. Instruc iunea while
using System;
namespace Exemplul_28
{
class Program
{
static void Main(string[] args)
{
int n = 0;
while (n <= 10)
{
Console.Write("{0,3}", n);
n++;
}
Console.ReadLine();
}
}
}
36
Exemplul 29: Programul de mai jos num r câte cifre pare are un num r natural:
using System;
namespace Exemplul_29
{
class Program
{
static void Main(string[] args)
{
uint a = 1223466, b;
b = CateCifrePare(a);
Console.WriteLine("Numarul {0} are {1} cifre pare", a, b);
}
static uint CateCifrePare(uint a)
{
uint k = 0;
if (a == 0) k = 1;
while (a != 0)
{
if (a % 10 % 2 == 0) k++; // sau if(a % 2 == 0)
// pentru ca a numar par daca si numai daca ultima cifra este
para
a = a / 10;
}
return k;
}
}
}
Exemplul 30: S se calculeze cmmdc i cmmmc pentru dou numere citite de la tastatur .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_30
{
class Program
{
static void Main(string[] args)
{
int a, b, r, x, y;
Console.Write("Dati primul numar : ");
a = Convert.ToInt32(Console.ReadLine());
37
Console.Write("Dati al doilea numar : ");
b = Convert.ToInt32(Console.ReadLine());
x = a;
y = b;
r = x % y;
while (r != 0)
{
x = y;
y = r;
r = x % y;
}
if (y != 1)
Console.WriteLine("Cmmdc ({0}, {1}) = {2} ", a, b, y);
else
Console.WriteLine("{0} si {1} sunt prime intre ele ", a, b);
Console.WriteLine("Cmmmc ({0}, {1}) = {2}", a, b, a / y * b);
Console.ReadKey();
}
}
}
Exemplul 31: Dintr-un num r întreg pozitiv, citit de la tastatur , s se elimine cifra cea mai mic i
s se afi eze num rul rezultat în urma acestei opera ii.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_31
{
class Program
{
static void Main(string[] args)
{
uint n, min, v;
Console.Write("Dati un numar intreg pozitiv : ");
n = Convert.ToUInt32(Console.ReadLine());
min = MinCifra(n);
v = Valoare(n, min);
Console.WriteLine("Eliminand cifra minima {0} din {1} obtinem
{2}", min, n, v);
}
38
static uint MinCifra(uint x)
{
uint min = 9;
while (x != 0)
{
if (x % 10 < min) min = x % 10;
x /= 10;
}
return min;
}
static uint Valoare(uint x, uint min)
{
uint y = 0, p = 1;
while (x != 0)
{
if (x % 10 != min)
{
y = y + (x % 10) * p;
p *= 10;
}
x /= 10;
}
return y;
}
}
}
do
Instructiuni;
while(conditie)
Se execut Instructiuni dup care se verific conditie. Dac aceasta este adev rat ,
ciclul se reia, altfel ciclul se termin .
39
Exemplul 32: Asem n tor cu exerci iul 28, s se afi eze numerele întregi pozitive <= 10
using System;
namespace Exemplul_32
{
class Program
{
static void Main(string[] args)
{
int n = 0;
do
{
Console.Write("{0,3}", n);
n++;
}
while (n <= 10) ;
Console.ReadLine();
}
}
}
Exemplul 33: S se afi eze numerele cu proprietatea de a fi palindroame, pân la o valoare citit
de la tastatur . De asemenea, s se afi eze i num rul lor.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_33
{
class Program
{
static void Main(string[] args)
{
int x, n, k = 0;
do
{
Console.Write("Dati un numar natural : ");
n = Convert.ToInt32(Console.ReadLine());
if (n <= 0)
Console.WriteLine("Eroare la citire!");
} while (n <= 0);
Console.Write("Numerele palindroame mai mici strict decat {0}
sunt :\n", n);
x = 1;
40
do
{
if (palindrom(x) == 1)
{
Console.Write(" {0,3} ", x);
k++;
}
x++;
} while (x < n);
Console.WriteLine();
if (k == 0) Console.WriteLine("Nu exista numere!");
else Console.WriteLine("Sunt {0} numere palindroame!", k);
}
static uint palindrom(int x)
{
int y = 0, z = x;
do
{
y = y * 10 + z % 10;
z /= 10;
} while (z != 0);
if (y == x) return 1;
else return 0;
}
}
}
41
Exemplul 34: Ne propunem, s afi m numerele pozitive <=10
using System;
namespace Exemplul_34
{class Program
{static void Main(string[] args)
{
for (int n = 0; n <= 10; n++)
{
Console.Write("{0,3}", n);
}
Console.ReadLine();
}
}
}
Exemplul 35: S se determine numerele prime, precum i num rul lor, cuprinse între dou valori
întregi citite de la tastatur .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_35
{
class Program
{
static void Main(string[] args)
{
int a, b, x, k = 0; // k va determina cate numere prime sunt in
interval
do
{
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
} while (a <= 0);
do
{
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
} while (b <= a);
42
Console.Write("Numerele prime : ");
for (x = a; x <= b; x++)
if (prim(x) == 1)
{
Console.Write("{0, 3}", x);
k++;
}
Console.WriteLine();
if (k == 0)
Console.WriteLine("In intervalul [ {0}, {1} ] nu sunt numere
prime!", a, b);
else
Console.WriteLine("In intervalul [ {0}, {1} ] sunt {2} numere
prime!", a, b, k);
}
static int prim(int x)
{
if (x == 1) return 0;
if (x % 2 == 0 && x != 2) return 0;
for (int d = 3; d * d <= x; d += 2)
if (x % d == 0) return 0;
return 1;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_36
{
class Program
{
static void Main(string[] args)
{
double rc, ic;
double x, y, z;
int n;
for (ic = 1.4; ic >= -1.4; ic -= 0.05)
{
for (rc = -0.7; rc <= 1.80; rc += 0.05)
{
43
n = 0;
x = ic * ic + rc * rc;
y = 2 * ic - 4 * rc;
z = x * x + y * y;
while (n <= 40 && z < 5)
{
x = ic * ic + rc * rc - rc;
y = 2 * ic - 4 * rc;
z = x * x - y * y;
n++;
}
switch (n % 4)
{
case 0: Console.Write("*"); break;
case 1: Console.Write("$"); break;
case 2: Console.Write("o"); break;
case 3: Console.Write("@"); break;
}
}
Console.WriteLine();
}
}
}
}
44
I.2.6.6. Instruc iunea foreach
O instruc iune nou , pe care o aduce limbajul C#, este foreach. Aceast instruc iune
enumer elementele dintr-o colec ie, executând o instruc iune pentru fiecare element. Elementul
care se extrage este de tip read-only, neputând fi transmis ca parametru i nici aplicat un operator
care s -i schimbe valoarea.
45
Pentru a vedea cum ac ioneaz , o vom compara cu instruc iunea cunoscut for.
Consider m un vector nume format din iruri de caractere:
using System;
namespace Exemplul_37
{
class Program
{
static void Main(string[] args)
{
string sir = "Acesta este un sir";
char[] delimitator = { ' ', ',', '.', ':' };
Console.WriteLine("Sirul care va fi impartit in cuvinte
\n‘{0}’", sir);
string[] cuvant = sir.Split(delimitator);
Console.WriteLine("Sunt {0} cuvinte in text:", cuvant.Length);
foreach (string s in cuvant)
{
Console.WriteLine(s);
}
}
}
}
46
I.2.6.7. Instruc iunea goto
Instruc iunea goto poate fi folosit , în C#, pentru efectuarea unor salturi, în instruc iunea
switch
Exemplul 38:
switch (a)
{
case 13:
x = 0;
y = 0;
goto case 20;
case 15:
x = 3;
y = 1;
goto default;
case 20:
x = 5;
y = 8;
break;
default:
x = 1;
y = 0;
break;
}
Instruc iunea continue permite reluarea itera iei celei mai apropiate instruc iuni switch,
while, do – while, for sau foreach.
47
Exemplul 39:
using System;
namespace Exemlul_39
{
class Program
{
static void Main(string[] args)
{
int i = 0;
while (true)
{
Console.Write("{0} ", i);
i++;
if (i < 10)
continue;
else
break;
}
Console.ReadLine();
}
}
}
Prin excep ie se în elege un obiect care încapsuleaz informa ii despre situa ii anormale. Ea
se folose te pentru a semnala contextul în care apare o situa ie special .
Exemple: erori la deschiderea unor fi iere a c ror nume este gre it, împ r ire la 0 etc. Aceste
erori se pot manipula astfel încât programul s nu se pr bu easc .
Când o metod întâlne te o situa ie dintre cele men ionate mai sus, se va „arunca” o
excep ie care trebuie sesizat i tratat . Limbajul C# poate arunca ca excep ii obiecte de tip
System.Exception sau derivate ale acestuia. Aruncarea excep iilor se face cu instruc iunea
throw
Prinderea i tratarea excep iilor se face folosind un bloc catch. Pot exista mai multe blocuri
catch, fiecare dintre ele prinde i trateaz o excep ie.
48
Pentru a garanta c un anumit cod se va executa indiferent dac totul decurge normal sau
apare o excep ie, acest cod se va pune în blocul finally care se va executa în orice situa ie.
Exemplul 40:
Presupunem c dorim s citim fi ierul „Gigel.txt”
using System;
using System.IO;
namespace Exemplul_40
{
class tryCatch
{
static void Main(string[] args)
{
File.OpenRead("Gigel.txt");
}
}
}
Pentru a remedia aceast eroare, vom prinde excep ia, punând într-un bloc try linia care a
furnizat-o.
Putem vizualiza mesajul produs de excep ia întâlnit :
49
using System;
using System.IO;
namespace Exemplul_40
{
class tryCatch
{
static void Main(string[] args)
{
try
{
File.OpenRead("Gigel.txt");
}
catch (FileNotFoundException a)
{
Console.WriteLine(a);
}
finally
{
Console.WriteLine("Acest bloc se va executa");
Console.ReadLine();
}
}
}
}
50
using System;
using System.IO;
namespace Exemplul_40
{
class tryCatch
{
static void Main(string[] args)
{
try
{
File.OpenRead("Gigel.txt");
}
catch (FileNotFoundException a)
{
Console.WriteLine("Nu exista fisierul cerut de dv.");
}
finally
{
Console.WriteLine("Acest bloc se va executa");
Console.ReadLine();
}
}
}
}
Alteori putem simula prin program o stare de eroare, „aruncând” o excep ie (instruc iunea
throw) sau putem profita de mecanismul de tratare a erorilor pentru a implementa un mecanism
de validare a datelor prin generarea unei excep ii proprii pe care, de asemenea, o „arunc m” în
momentul neîndeplinirii unor condi ii puse asupra datelor.
Clasa System.Exception i derivate ale acesteia servesc la tratarea adecvat i
diversificat a excep iilor.
51
I.2.7. Tablouri
Limbajul C# trateaz tablourile într-o manier nou fa de alte limbaje (Pascal, C/C++).
La declararea unui tablou, se creeaz o instan a clasei .NET, System.Array. Compilatorul va
traduce opera iile asupra tablourilor, apelând metode ale System.Array.
Declararea unui tablou unidimensional se face astfel:
Tip[] nume;
Prin aceast declara ie nu se aloc i spa iu pentru memorare. Pentru aceasta, tabloul
trebuie instan iat:
Se pot face în acela i timp opera iile de declarare, instan iere i ini ializare:
Exemplu:
sau
int[] v = {1,2,3);
foreach (int i in v)
Console.Write("{0,3}",i);
52
Exemplul 42: S se afi eze num rul de elemente de pe a doua linie a tabloului i num rul total de
linii.
using System;
namespace Exemplul_42
{ class Program
{static void Main(string[] args)
{
int[,] tab = { { 1, 2, 3 }, { 4, 5, 6 } };
// Afisarea numarului de elemente ale
// lui tab de pe linia a 2-a.
// Reamintim ca prima linie are numarul de ordine 0
Console.WriteLine(tab.GetLength(1));
// Afisarea numarului de linii a tabloului tab
Console.WriteLine(tab.Rank);
Console.ReadLine();
}
}
}
Exemplul 43: S se afi eze primele n+1 linii din triunghiul lui PASCAL(n 20).
using System;
namespace Exemplul_43
{
class Program
{
static void Main()
{
int n, i, j; int[] p, q;
n = Convert.ToInt32(Console.ReadLine());
p = new int[n + 1]; q = new int[n + 1];
p[0] = 1;
for (i = 1; i <= n + 1; i++)
{
q[0] = 1; q[i - 1] = 1;
for (j = 1; j <= i - 2; j++)
q[j] = p[j - 1] + p[j];
for (j = 0; j <= i - 1; j++)
{
Console.Write(q[j] + " ");
p[j] = q[j];
}
Console.WriteLine();
}
}
}
}
53
Exemplul 44: Ciurul lui Eratostene. Pentru un num r natural n dat se afi eaz toate numerele
prime mai mici decât n. Selectarea numerelor prime se face folosind ciurul lui Eratostene
Ciurul lui Eratostene presupune formarea unui ir din numerele 2, 3, 4, …, n-1, n. Pentru a
ob ine acest ir „t iem” mai întâi to i multiplii lui 2, apoi ai lui 3 .a.m.d. În final r mân numai
numerele prime din intervalul [2,n]. No iunea de „t iere” a unui element va însemna, în acest caz,
atribuirea valorii zero pentru acel element.
using System;
namespace Exemplul_44
{
class Program
{
static void Main()
{
int n, i, j, k;
int[] c;
n = Convert.ToInt32(Console.ReadLine());
c = new int[n + 1];
for (i = 2; i <= n; i++)
c[i] = i;
i = 2;
while (i <= n / 2)//cel mai mare divizor propriu al unui numar
este<=jumatatea sa
{
if (c[i] != 0)
{
j = 2 * i;
while (j <= n)
{
if (c[j] != 0) c[j] = 0;
j += i;
}
}
i++;
}
for (i = 2; i <= n; i++)
if (c[i] != 0)
Console.Write(c[i] + " ");
Console.WriteLine();
}
}
}
54
Exemplul 45: Ionel urc în fiecare zi n trepte(n<40) pân la apartamentul în care locuie te. El
poate urca p ind pe treapta urm toare sau s rind peste o treapt . În câte moduri poate urca Ionel
cele n trepte?
Dac not m cu f[i] num rul de moduri în care poate urca copilul i trepte, observ m c exist
2 moduri prin care acesta poate ajunge la treapta i: de la treapta i-1 sau de la treapta i-2. Pentru a
determina num rul de moduri, vom însuma în câte moduri poate ajunge pe treapta i-1 cu num rul
de modalit i de a ajunge pe treapta i-2, deci f[i]=f[i-1]+f[i-2].
using System;
namespace Exemplul_45
{
class Program
{
static void Main()
{
int n, i;
int[] f;
Console.Write("Numarul de trepte = ");
n = Convert.ToInt32(Console.ReadLine());
f = new int[n + 1];
f[1] = f[2] = 1;
for (i = 3; i <= n; i++) f[i] = f[i - 1] + f[i - 2];
Console.WriteLine("Numarul de posibilitati este =
{0}",f[n].ToString());
Console.ReadLine();
}
}
}
55
Exemplul 46: S se determine valoare elementului maxim dintr-un tablou unidimensional, precum
i frecven a sa de apari ie
using System;
namespace Exemplul_46
{
class Program
{
static void Main(string[] args)
{
int n, i, max, f;
int[] a;
Console.Write("Dati dimensiunea tabloului : ");
n = Convert.ToInt32(Console.ReadLine());
a = new int[n + 1];
for (i = 0; i < n; i++)
{
Console.Write(" a[ {0} ] = ", i + 1);
a[i] = Convert.ToInt32(Console.ReadLine());
}
max = a[0];
f = 1;
for (i = 1; i < n; i++)
if (a[i] > max)
{
max = a[i];
f = 1;
}
else
if (a[i] == max) f++;
Console.WriteLine("Maximul din tablou este {0} cu frecventa {1}
", max, f);
}
}
}
56
Exemplul 47: Opera ii cu elementele unui vector: citire, afi are, eliminare elemente de valoare 0,
inserare dup fiecare valoare a celei mai apropiate puteri ale lui 2 (dac cele dou puteri sunt la
aceea i distan fa de num r se va insera cea mai mic dintre cele doua puteri)
using System;
namespace Exemplul_47
{
class Program
{
static void Main(string[] args)
{
int n, i, j, k = 0;
int[] a;
Console.Write("Dati dimensiunea tabloului : ");
n = Convert.ToInt32(Console.ReadLine());
a = new int[2 * n + 1];
Console.WriteLine("Citire tablou : ");
for (i = 0; i < n; i++)
{
Console.Write(" a[ {0} ] = ", i + 1);
a[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Afisare tablou : ");
for (i = 0; i < n; i++)
Console.Write("{0} ", a[i]);
Console.WriteLine();
// stergere valori nule
i = 0;
while (a[i] != 0 && i < n) i++;
while (i < n)
{
if (a[i] == 0)
{
for (j = i; j < n && a[j] == 0; j++) ;
a[i++] = a[j];
a[j] = 0;
k++;
}
else i++;
}
while (a[n - 1] == 0 && n > 0) n--;
Console.WriteLine("Afisare tablou fara valori nule : ");
for (i = 0; i < n; i++)
Console.Write("{0} ", a[i]);
Console.WriteLine();
// inserare valori
for (i = 0; i < n; i += 2)
{
for (j = n; j > i; j--)
a[j] = a[j - 1];
a[i + 1] = putere(a[i]);
n++;
}
Console.WriteLine("Afisare tablou dupa inserare puteri ale lui 2
: ");
for (i = 0; i < n; i++)
Console.Write("{0} ", a[i]);
Console.WriteLine();
}
57
static int putere(int x)
{
int p = 1, q;
while (p <= x) p *= 2;
q = p / 2;
if (x - q <= p - x) return q;
else return p;
}
}
}
În cazul tablourilor cu mai multe dimensiuni facem distinc ie între tablouri regulate i
tablouri neregulate (tablouri de tablouri)
Declararea în cazul tablourilor regulate bidimensionale se face astfel:
Tip[,] nume;
Accesul:
nume[indice1,indice2]
58
Exemplu: Declararea instan ierea i ini ializarea
sau
sau
Acces
nume[indice1][indice2]
59
Exemple:
sau
int[][] mat = {
new int[3] { 1, 2, 3 },
new int[2] { 4, 5 },
new int[4] { 7, 8, 9, 1 }
};
Exemple:
Exemplul 48: Descompunerea unui num r în sum de numere naturale consecutive. Se cite te un
num r natural n. S se memoreze toate posibilit ile de descompunere a num rului n în sum de
numere consecutive.
Dac num rul n se scrie ca sum de numere naturale consecutive, atunci rezult c exist
i,k N* astfel încât
i+(i+1)+(i+2)+(i+3)+……+(k)=n
(1+2+...+k)-(1+2+...+i-1)=n k*(k+1)/2-i*(i-1)/2=n
k2+k-i2+i-2n=0
k=(-1+ 1 8n - 4i 4i 2 )/2
Vom memora descompunerile în matricea neregulat a (descompunerile au dimensiuni
variabile).
60
using System;
namespace Exemplul_48
{
class Program
{
static void Main()
{
Console.Write("Introduceti un numar natural ");
int n = Convert.ToInt32(Console.ReadLine());
int[][] a = new int[n / 2][];
int l = 0, i, j;
for (i = 1; i <= n / 2; i++)
{
double k = (Math.Sqrt(1 + 8 * n - 4 * i + 4 * i * i) - 1)/ 2;
if (k == (int)k)
{
a[l] = new int[(int)k - i + 1];
for (j = i; j <= k; j++) a[l][j - i] = j;
l++;
}
}
Console.WriteLine("Descompunerea lui {0} in suma de numere
naturale consecutive", n);
for (i = 0; i < l; i++)
{
for (j = 0; j < a[i].Length; j++)
Console.Write(a[i][j] + " ");
Console.WriteLine();
}
}
}
}
Exemplul_49: Pentru o matrice p tratic , ale c rei elemente întregi se citesc de la tastatur , s se
determine:
maximul dintre valorile situate deasupra diagonalei principale
num rul de numere prime (dac acestea exist ) situate sub diagonala secundar
61
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_49
{
class Program
{
static void Main(string[] args)
{
int i, j, n;
Console.Write("Dati dimensiunea matricei patratice : ");
n = Convert.ToInt32(Console.ReadLine());
int[,] a;
a = new int[n + 1, n + 1];
Console.WriteLine("Citire matrice : ");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
Console.Write("a[{0}][{1}] = ", i + 1, j + 1);
a[i, j] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Afisare matrice : ");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
Console.Write("{0, 4}", a[i, j]);
Console.WriteLine();
}
int max = a[0, 1];
for (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (a[i, j] > max) max = a[i, j];
Console.WriteLine("Maximul dintre valorile situate deasupra
diagonalei principale : {0}", max);
int k = 0;
for (i = 1; i < n; i++)
for (j = n - i; j < n; j++)
if (prim(a[i, j]) == 1) k++;
if (k == 0)
Console.WriteLine("Sub diagonala secundara nu sunt numere
prime!");
else
Console.WriteLine("Sub diagonala secundara sunt {0} numere
prime!", k);
}
static int prim(int x)
{
if (x == 1) return 0;
if (x % 2 == 0 && x != 2) return 0;
for (int d = 3; d * d <= x; d += 2)
if (x % d == 0) return 0;
return 1;
}
}
}
62
I.2.8. iruri de caractere
Pentru reprezentarea irurilor de caractere, în limbajul C#, tipul de date utilizat este clasa
System.String (sau aliasul string). Se definesc dou tipuri de iruri:
regulate
de tip „Verbatim”
Tipul regulat con ine între ghilimele zero sau mai multe caractere, inclusiv secven e escape.
63
Limbajul C# introduce, pe lâng irurile regulate i cele de tip verbatim. În cazul în care
folosim multe secven e escape, putem utiliza irurile verbatim. Aceste iruri se folosesc în
special în cazul în care dorim s facem referiri la fi iere, la prelucrarea lor, la regi tri. Un astfel de
ir începe cu simbolul „@” înaintea ghilimelelor de început.
Exemplu:
using System;
namespace SiruriDeCaractere
{
class Program
{
static void Main(string[] args)
{
string a = "un sir de caractere";
string b = "linia unu \nlinia doi";
string c = @"linia unu
linia doi";
string d = "c:\\exemple\\unu.cs";
string e = @"c:\exemple\unu.cs";
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Console.WriteLine(e);
Console.ReadLine();
}
}
}
Secven Efect
escape
\’ apostrof
\” ghilimele
\\ backslash
\0 null
\a alarm
\b backspace
\f form feed – pagin nou
\n new line – linie nou
\r carriage return – început de rând
64
\t horizontal tab – tab orizontal
\u caracter unicode
\v vertical tab – tab vertical
\x caracter hexazecimal
I.2.8.1. Concatenarea irurilor de caractere
Exemplu:
Pentru a compara dou iruri de caractere vom utiliza operatorii “==” i “!=”.
Defini ie: dou iruri se consider egale dac sunt amândou null, sau dac amândou
au aceea i lungime i pe fiecare pozi ie au caractere respectiv identice. În caz contrar irurile se
consider diferite.
Exemplul 50: Exemplul urm tor demonstraz c operatorul “==” este definit pentru a compara
valoarea obiectelor string i nu referin a lor
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_50
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul C#";
string b = "Invat " + "limbajul ";
b += "C#";
Console.WriteLine("a='{0}'", a);
Console.WriteLine("b='{0}'", b);
Console.WriteLine("a == b {0}", a == b);
Console.WriteLine("(object)a == b {0}", (object)a == b);
}
}
}
65
I.2.8.1. Func ii importante pentru iruri
Clasa String pune la dispozi ia utilizatorului mai multe metode i propriet i care permit
prelucrarea irurilor de caractere. Dintre acestea amintim:
metode de comparare:
- Compare
- CompareOrdinal
- CompareTo
metode pentru c utare:
- EndsWith
- StartsWith
- IndexOf
- LastIndexOf
metode care permit modificarea irului curent prin ob inerea unui nou ir:
- Concat
- CopyTo
- Insert
- Join
- PadLeft
- PadRight
- Remove
- Replace
- Split
- Substring
- ToLower
- ToUpper
- Trim
- TrimEnd
- TrimStart
Proprietatea Length am folosit-o pe parcursul acestei lucr ri i, dup cum tim returneaz un
întreg care reprezint lungimea (num rul de caractere) irului.
66
Tabelul de mai jos prezint câteva dintre func iile (metodele) clasei String
Func ia (metod a clasei Strig) Descrierea
string Concat(string u, string v) returneaz un nou ir ob inut prin concatenarea
irurilor u i v
int IndexOf(char c) returneaz indicele primei apari ii a caracterului
c în ir
int IndexOf(string s) returneaz indicele primei apari ii a sub irului s
string Insert(int a, string s) returneaz un nou ir ob inut din cel ini ial prin
inserarea în irul ini ial, începând cu pozi ia a,
a irului s
string Remove(int a, int b) returneaz un nou ir ob inut din cel ini ial prin
eliminarea, începând cu pozi ia a, pe o lungime
de b caractere
string Replace(string u, string v) returneaz un nou ir ob inut din cel ini ial prin
prin înlocuirea sub irului u cu irul v
string Split(char[] c) împarte un ir în func ie de delimitatorii c
string Substring(int index) returneaz un nou ir care este un sub ir al
irului ini ial începând cu indicele index
string Substring(int a, int b) returneaz un nou ir care este un sub ir al
irului ini ial, începând de pe pozi ia a, pe
lungimea b caractere
string ToLower() returneaz un nou ir ob inut din cel ini ial prin
convertirea tuturor caracterelor la minuscule
string ToUpper() returneaz un nou ir ob inut din cel ini ial prin
convertirea tuturor caracterelor la majuscule
string Trim() returneaz un nou ir ob inut din cel ini ial prin
tergerea spa iilor goale de la începutul i
sfâr itul irului ini ial
string TrimEnd() returneaz un nou ir ob inut din cel ini ial prin
tergerea spa iilor goale de la sfâr itul irului
ini ial
string TrimStart() returneaz un nou ir ob inut din cel ini ial prin
tergerea spa iilor goale de la începutul irului
ini ial
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_51
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul ";
string b = "C#";
string c;
Console.WriteLine("a = '{0}'", a);
Console.WriteLine("b = '{0}'", b);
67
c = string.Concat(a, b);
Console.WriteLine("string.Concat(a, b) = \"{0}\"", c);
Console.WriteLine("a.IndexOf(\"v\") = {0}",
Convert.ToString(a.IndexOf("v")));
Console.WriteLine("a.IndexOf(\"mba\") = {0}",
Convert.ToString(a.IndexOf("mba")));
Console.WriteLine("a.Insert(6, \"de zor \") = {0}", a.Insert(6,
"de zor "));
Console.WriteLine("a.Remove(5, 7) = {0}", a.Remove(5, 7));
Console.WriteLine("a.Replace(\"limbajul \", \"la informatica.\")
= {0}", a.Replace("limbajul ", "la informatica."));
Console.WriteLine("a.Substring(6) = {0}", a.Substring(6));
Console.WriteLine("a.Substring(10, 3) = {0}", a.Substring(10,
3));
Console.WriteLine("a.ToLower() = {0}", a.ToLower());
Console.WriteLine("a.ToUpper() = {0}", a.ToUpper());
string d = " Ana are mere. ";
Console.WriteLine("d = {0}", d);
Console.WriteLine("d.Trim() = {0}", d.Trim());
Console.WriteLine("d.TrimStart() = {0}", d.TrimStart());
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_52
{
class Majuscule
{
static void Main()
{
int i, nrm = 0;
string text = System.Console.ReadLine();
68
for (i = 0; i < text.Length; i++)
{ if (text[i] >= 'A' && text[i] <= 'Z') nrm++; }
System.Console.WriteLine("numarul de majuscule este=" + nrm);
}
}
}
Exemplul 53: S se verifice dac cuvintele s1 i s2 citite de la tastatur au aceea i textur . Dou
cuvinte au aceea i textur dac au aceea i lungime i toate caracterele corespondente au acela i
tip. Nu se face distinc ie între litere mari, litere mici.
Ex : acum i elev au aceea i textur (vocal consoan vocal consoan )
using System;
namespace Exemplul_53
{
class Program
{
private static bool strchr(string p, char p_2)
{
for (int i = 0; i < p.Length; i++)
if (p[i] == p_2) return true;
return false;
}
static void Main()
{
String s1 = Console.ReadLine();
String s2 = Console.ReadLine();
String v = string.Copy("aeiouAEIOU");
bool textura = true;
int i;
if (s1.Length != s2.Length) textura = false;
else
{
for (i = 0; i < s1.Length; i++)
if (strchr(v, s1[i]) && !strchr(v, s2[i]) || !strchr(v,
s1[i]) && strchr(v, s2[i]))
textura = false;
}
if (textura) Console.WriteLine("Au aceeasi textura");
else Console.WriteLine("Nu au aceeasi textura");
}
}
}
69
Exemplul 54: Folosind metoda Split, s se numere cuvintele unui text tiind c acestea sunt
separate printr-un singur separator din mul imea { ' ', ',', ';'}.
using System;
namespace Exemplul_54
{
class Program
{
static void Main(string[] args)
{
String s = "Metoda Split() nu face gruparea mai multor
separatori";
char[] x = { ' ', ',', ';' };
String[] cuvant = s.Split(x);
int nrcuv = 0;
for (int i = 0; i < cuvant.Length; i++)
{
Console.WriteLine(cuvant[i]);
nrcuv++;
}
Console.WriteLine("Textul contine {0} cuvinte.",nrcuv);
}
}
}
Metoda Split() nu face gruparea mai multor separatori, lucru care ar fi de dorit. Pentru
aceasta se folosesc expresii regulate.
70
Expresiile regulate reprezint o metod extrem de util pentru a opera c ut ri/înlocuiri pe
text.
Exemplul 55:
using System;
using System.Text.RegularExpressions;
namespace Exemplul_55
{
class Program
{
static void Main(string[] args)
{
String s = "Expresiile regulate , reprezinta o metoda extrem
de facila de a opera cautari, ınlocuiri pe text. ";
//separator: virgula, spatiu sau punct si virgula
//unul sau mai multe, orice combinatie
Regex regex = new Regex("[, ;]+");
String[] cuvant = regex.Split(s);
for (int i = 0; i < cuvant.Length; i++)
{
Console.WriteLine(cuvant[i]);
}
Console.ReadKey();
}
}
}
71
I.2.9. Stocarea informa iilor în fi iere
Tehnica de citire i scriere a datelor în i din fi iere, utilizat pentru a p stra aceste
informa ii, reprezint administrarea fi ierelor.
Pentru accesarea unui fi ier de pe disc se folosesc func ii din spa iul de nume System.IO.
În acest spa iu exist mai multe clase: File, StreamWriter, BinaryReader i
BinaryWriter.
Aceste clase sunt folosite pentru opera iile de intrare-ie ire cu fi iere.
Obiectul File este o reprezentare a unui fi ier de pe disc, iar pentru a-l utiliza trebuie s îl
conect m la un flux (stream).
Pentru a scrie datele pe disc, se ata eaz unui flux un obiect File. Astfel se face
administrarea datelor.
Limbajul C# ofer dou tipuri de fi iere: fi iere text i fi iere binare.
Exemplul 56:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Exemplul_56
{
class Program
{
static void Main(string[] args)
{
string[] a = { "primul", "fisier", "creat", "de mine", };
//deschiderea unui fisier si atasarea lui la un flux
StreamWriter outputFile = File.CreateText("C:\\C#\\fisier1.txt");
72
foreach (string b in a)
{
outputFile.WriteLine(b);//scrierea textului in fisier
}
//inchiderea fisierului
outputFile.Close();
//deschidem din nou fisierul de data aceasta pentru a citi din el
StreamReader inputFile = File.OpenText("C:\\C#\\fisier1.txt");
//definim o variabila string care va parcurge fisierul pana la
final
string x;
while ((x = inputFile.ReadLine()) != null)
{
System.Console.WriteLine(x);
}
//inchidem fisierul
inputFile.Close();
}
}
}
Dac la fi ierele text tipul de flux folosit era StreamWriter, la cele binare, pentru scrierea
datelor programul creeaz un obiect FileStream, la care trebuie ata at i un obiect
BinaryWriter.
73
Exemplul 57:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Exemplul_57
{
class Program
{
static void Main(string[] args)
{
int i, j, x;
int[,] a = new int[10, 10];
//se creeaza un fisier si un flux
FileStream f = new FileStream("C:\\C#\\fisier2.dat",
FileMode.CreateNew);
// se creeaza un scriitor binar si il ataseaza la flux
//acesta traduce datele fluxului in format binar
BinaryWriter outputFile = new BinaryWriter(f);
for (i = 1; i <= 4; i++)
for (j = 1; j <= 4; j++)
if (i == j) a[i, j] = 1;
else if (j == 5 - i) a[i, j] = 2;
else a[i, j] = 0;
for (i = 1; i <= 4; i++)
for (j = 1; j <= 4; j++)
outputFile.Write(a[i, j]);
//se inchide fisierul creat
outputFile.Close();
f.Close();
//incepe citirea datelor din fisierul creat mai sus
//se creeaza un obiect FileStream
FileStream g = new FileStream("C:\\C#\\fisier2.dat",
FileMode.Open);
//se creeaza un obiect BinaryReader
BinaryReader inputFile = new BinaryReader(g);
bool final;
for (final = false, i = 1; !final; i++)
{
for (final = false, j = 1; !final; j++)
{//se apeleaza functia PeekChar care face parte din clasa
BinaryReader
//si examineaza urmatorul caracter din flux, daca acesta
este diferit de -1
// atunci se executa citirea urmatorului caracter din
flux prin functia ReadInt32()
if (inputFile.PeekChar() != -1)
{
x = inputFile.ReadInt32();
System.Console.Write("{0} ", x);
}
}
System.Console.Write("\n");
}
inputFile.Close();
g.Close();
}
}
}
74
I.3. Principiile program rii orientate pe obiecte
modul_1 modul_2
(date+date1) (date+date2)
subprog_1 subprog_1
subprog_2 subprog_2
subprog_3
Se observ c modulele sunt „centrate” pe proceduri, acestea gestionând i setul de date pe care
le prelucreaz (date+date1 din figur ). Dac , de exemplu, dorim s avem mai multe seturi diferite
de date, toate înzestrate comportamental cu procedurile din modulul modul_1, aceast arhitectur
de aplica ie nu este avantajoas .
Programarea orientat obiect – POO (programe cu noi tipuri ce integreaz atât datele, cât
i metodele asociate cre rii, prelucr rii i distrugerii acestor date); se ob in avantaje prin
75
abstractizarea program rii (programul nu mai este o succesiune de prelucr ri, ci un ansamblu de
obiecte care prind
obiect1 obiect4
date1 date4
met1 met4
obiect3
obiect2 date3
met3
date2
met2
via , au diverse propriet i, sunt capabile de ac iuni specifice i care interac ioneaz în cadrul
programului); intervin tehnici noi privind instan ierea, derivarea i polimorfismul tipurilor obiectuale.
Defini ie: Un tip de date abstract (ADT) este o entitate caracterizat printr-o structur de
date i un ansamblu de opera ii aplicabile acestor date.
Defini ie: Opera iile care sunt accesibile din afara ADT formeaz interfa a acesteia. Astfel,
opera ii interne cum ar fi conversia datei de na tere la un num r standard calculat de la
01.01.1900 nu fac parte din interfa a tipului de date abstract, în timp ce opera ia „plaseaz o
comand on-line” face parte, deoarece permite interac iunea cu alte obiecte (SITE, STOC etc.).
Defini ie: Numim instan a unui tip de date abstract o „concretizare” a tipului respectiv,
format din valori efective ale datelor.
Defini ie: Un tip de date obiectual este un tip de date care implementeaz un tip de date
abstract.
76
Defini ie: Vom numi metode opera iile implementate în cadrul tipului de date abstract.
Defini ie: Numim membri ai unui tip de date obiectual datele i metodele definite mai sus.
Exemplul 58:
Un exemplu de-acum clasic de tip de date abstract este STIVA. Ea poate avea ca date:
numerele naturale din stiv , capacitatea stivei, vârful etc. Iar opera iile specifice pot fi: introducerea
în stiv (push) i extragerea din stiv (pop). La implementarea tipului STIVA, vom defini o structur
de date care s re in valorile memorate în stiv i câmpuri de date simple pentru: capacitate,
num r de elemente etc. Vom mai defini metode (subprograme) capabile s creeze o stiv vid ,
care s introduc o valoare în stiv , s extrag valoarea din vârful stivei, s testeze dac stiva este
vid sau dac stiva este plin etc.
Defini ie: Crearea unei instan e noi a unui tip obiectual, presupune opera ii specifice de
„construire” a noului obiect, metoda corespunz toare purtând numele de constructor.
Defini ie: La desfiin area unei instan e i eliberarea spa iului de memorie aferent datelor
sale, se aplic o metod specific numit destructor (datorit tehnicii de supraînc rcare, limbaje
de genul C++, Java i C# permit existen a mai multor constructori ).
O aplica ie ce utilizeaz tipul obiectual STIVA, va putea construi dou sau mai multe stive
(de c r i de joc, de exemplu), le va umple cu valori distincte, va muta valori dintr-o stiv în alta
dup o anumit regul desfiin ând orice stiv golit , pân ce r mâne o singur stiv . De observat
c toate aceste prelucr ri recurg la datele, constructorul, destructorul i la metodele din interfa a
tipului STIVA descris mai sus.
Defini ii: Principalul tip obiectual întâlnit în majoritatea mediilor de dezvoltare (Visual Basic,
Delphi, C++, Java, C#) poart numele de clas (class). Exist i alte tipuri obiectuale (struct,
object). O instan a unui tip obiectual poart numele de obiect.
Defini ie: La implementare, datele i metodele asociate trebuie s fie complet i corect
definite, astfel încât utilizatorul s nu fie nevoit s in cont de detalii ale acestei implement ri. El
77
va accesa datele, prin intermediul propriet ilor i va efectua opera iile, prin intermediul metodelor
puse la dispozi ie de tipul obiectual definit. Spunem c tipurile de date obiectuale respect
principiul încapsul rii.
Astfel, programatorul ce utilizeaz un tip obiectual CONT (în banc ) nu trebuie s poarte
grija modului cum sunt reprezentate în memorie datele referitoare la un cont sau a algoritmului prin
care se realizeaz actualizarea soldului conform opera iilor de depunere, extragere i aplicare a
dobânzilor. EL va utiliza unul sau mai multe conturi (instan e ale tipului CONT), accesând
propriet ile i metodele din interfa , realizatorul tipului obiectual asumându- i acele griji în
momentul definirii tipului CONT.
Permi ând extensia tipurilor de date abstracte, clasele pot avea la implementare:
date i metode caracteristice fiec rui obiect din clas (membri de tip instan ),
date i metode specifice clasei (membri de tip clas ).
Astfel, clasa STIVA poate beneficia, în plus, i de date ale clasei cum ar fi: num rul de stive
generate, num rul maxim sau num rul minim de componente ale stivelor existente etc.
Modificatorul static plasat la definirea unui membru al clasei face ca acela s fie un membru de
clas , nu unul de tip instan . Dac în cazul membrilor nestatici, exist câte un exemplar al
membrului respectiv pentru fiecare instan a clasei, membrii statici sunt unici, fiind accesa i în
comun de toate instan ele clasei. Mai mult, membrii statici pot fi referi i chiar i f r a crea vreo
instan a clasei respective.
I.3.3.Supraînc rcare
De i nu este o tehnic specific program rii orientat obiect, ea creeaz un anumit context
pentru metodele ce formeaz o clas i modul în care acestea pot fi (ca orice subprogram)
apelate.
Defini ie: Prin supraînc rcare se în elege posibilitatea de a defini în acela i domeniu de
vizibilitate mai multe func ii cu acela i nume, dar cu parametri diferi i ca tip i/sau ca num r.
Defini ie: Ansamblul format din numele func iei i lista sa de parametri reprezint o
modalitate unic de identificare numit semn tur sau amprent .
Supraînc rcarea permite ob inerea unor efecte diferite ale apelului în contexte diferite
Capacitatea unor limbaje (este i cazul limbajului C#) de a folosi ca „nume” al unui subprogram un
operator, reprezint supraînc rcarea operatorilor. Aceasta este o facilitate care „reduce”
78
diferen ele dintre operarea la nivel abstract (cu DTA) i apelul metodei ce realizeaz aceast
opera ie la nivel de implementare obiectual . De i ajut la sporirea expresivit ii codului, prin
supraînc rcarea operatorilor i metodelor se pot crea i confuzii.
Apelul unei func ii care beneficiaz , prin supraînc rcare, de dou sau mai multe semn turi
se realizeaz prin selec ia func iei a c rei semn tur se potrive te cel mai bine cu lista de
parametri efectivi (de la apel).
Astfel, poate fi definit metoda „comand on-line” cu trei semn turi diferite:
comanda_online(cod_prod) cu un parametru întreg (desemnând comanda unui singur
produs identificat prin cod_prod
comanda_online(cod_prod,cantitate) cu primul parametru întreg i celalalt real
comanda_online(cod_prod,calitate) cu primul parametru întreg i al-II-lea caracter.
I.3.4. Mo tenire
Defini ie: Pentru tipurile de date obiectuale class este posibil o opera ie de extindere sau
specializare a comportamentului unei clase existente prin definirea unei clase noi ce mo tene te
datele i metodele clasei de baz , cu aceast ocazie putând fi redefini i unii membri existen i sau
ad uga i unii membri noi. Opera ia mai poart numele de derivare.
Defini ii: Clasa din care se mo tene te se mai nume te clas de baz sau superclas .
Clasa care mo tene te se nume te subclas , clas derivat sau clas descendent .
79
Defini ie: O metod abstract este o metod pentru care nu este definit o implementare,
aceasta urmând a fi realizat în clasele derivate din clasa curent care trebuie s fie i ea
abstract (virtual pur , conform terminologiei din C++).
Defini ie: O metod sigilat este o metod care nu mai poate fi redefinit în clasele
derivate din clasa curent .
Defini ie: Folosind o extensie a sensului etimologic, un obiect polimorfic este cel capabil s
ia diferite forme, s se afle în diferite st ri, s aib comportamente diferite. Polimorfismul
obiectual, care trebuie s fie abstract, se manifest în lucrul cu obiecte din clase apar inând unei
ierarhii de clase, unde, prin redefinirea unor date sau metode, se ob in membri diferi i având îns
acela i nume.
Astfel, în cazul unei referiri obiectuale, se pune problema stabilirii datei sau metodei referite.
Comportamentul polimorfic este un element de flexibilitate care permite stabilirea contextual , în
mod dinamic, a membrului referit. Acest lucru este posibil doar în cazul limbajelor ce permit
„legarea întârziat ”. La limbajele cu „legare timpurie”, adresa la care se face un apel al unui
subprogram se stabile te la compilare. La limbajele cu legare întârziat , aceast adres se
stabile te doar in momentul rul rii, putându-se calcula distinct, în func ie de contextul în care apare
apelul.
Exemplul 59:
Dac este definit clasa numit PIESA (de ah), cu metoda nestatic muta (pozitie_initiala,
pozitie_finala), atunci subclasele TURN i PION trebuie s aib metoda muta definit în mod
diferit (pentru a implementa maniera specific a pionului de a captura o pies „en passant”, sau,
într-o alt concep ie, metoda muta poate fi implementat la nivelul clasei PIESA i redefinit la
nivelul subclasei PION, pentru a particulariza acest tip de deplasare care captureaz piesa peste
care trece pionul în diagonal ). Atunci, pentru un obiect T, apar inând claselor derivate din PIESA,
referirea la metoda muta pare nedefinit . Totu i mecanismele POO permit stabilirea, în momentul
apelului, a clasei proxime c reia îi apar ine obiectul T i apelarea metodei corespunz tore (mutare
de pion sau tur sau alt pies ).
Pentru a permite acest mecanism, metodele care necesit o decizie contextual (în
momentul apelului), se declar ca metode virtuale (cu modificatorul virtual). În mod curent, în C#
80
modificatorului virtual al func iei din clasa de baz , îi corespunde un specificator override al
func iei din clasa derivat ce redefine te func ia din clasa de baz .
O metod ne-virtual nu este polimorfic i, indiferent de clasa c reia îi apar ine obiectul, va
fi invocat metoda din clasa de baz .
Ideea POO este de a crea programele ca o colec ie de obiecte, unit i individuale de cod
care interac ioneaz unele cu altele, în loc de simple liste de instruc iuni sau de apeluri de
proceduri.
Obiectele POO sunt, de obicei, reprezent ri ale obiectelor din via a real (domeniul
problemei), astfel încât programele realizate prin tehnica POO sunt mai u or de în eles, de
depanat i de extins decât programele procedurale. Aceasta este adev rat mai ales în cazul
proiectelor software complexe i de dimensiuni mari.
Limbajul C# permite utilizarea program rii orientate pe obiecte respectând toate principiile
enun ate anterior.
Toate componentele limbajului sunt într-un fel sau altul, asociate no iunii de clas . Programul
însu i este o clas având metoda static Main() ca punct de intrare, clas ce nu se instan iaz .
81
Chiar i tipurile predefinite byte, int sau bool sunt clase sigilate derivate din clasa ValueType din
spa iul System. Tot din ierarhia de clase oferit de limbaj se ob in i tipuri speciale cum ar fi:
interfe e, deleg ri i atribute. Începând cu versiunea 2.0 a limbajului i s-a ad ugat un nou tip:
clasele generice, echivalentul claselor template din C++.
În cele ce urmeaz vom analiza, f r a intra în detalii o aplica ie POO simpl în C#.
unde:
public – sunt modificatori de acces.
class – cuvânt rezervat pentru no iunea de clas
Copil – numele clasei
{ } – corpul clasei Copil
Dac consider m clasa Copil ca i clas de baz ,
putem deriva dou clase Feti a i B iat Fetita Baiat
unde:
modificatorul sealed a fost folosit pentru a desemna faptul c nu se mai pot ob ine clase derivate
din clasa Baiat
I.4.2. Constructori
82
Instan ierea presupune declararea unei variabile de tipul clasei respective i ini ializarea acesteia
prin apelul constructorului clasei (unul dintre ei, dac sunt defini i mai mul i) precedat de operatorul
new.
Exemplul 60:
83
public class Copil
{
protected string nume; //data accesibila numai in interiorul
//clasei si a claselor derivate
public Copil ( ) //constructorul fara parametrii ai clasei
{nume = Console.ReadLine( );}
public Copil (string s) //constructor cu parametru
{nume = s;}
}
class Fetita: Copil
{
public Fetita (string s): base(s) //base semnifica faptul ca
{ //se face apel la
nume = "Fetita "+ nume; //constructorul
//din clasa de baza
} }
...
Copil c1 = new Copil ( ); //numele copilului se citeste de la
//tastatura
Copil c2 = new Copil ("Gigel"); //numele lui c2 va fi Gigel
Fetita f1 = new Fetita ( );
Fetita f2 = new Fetita ("Maria");
I.4.4. Destructor
Corpul destructorului este format din instruc iuni care se execut la distrugerea unui obiect al
clasei respective. Pentru orice clas poate fi definit un singur constructor. Destructorii nu pot fi
mo teni i. În mod normal, destructorul nu este apelat în mod explicit, deoarece procesul de
distrugere a unui obiect este invocat i gestionat automat de Garbage Collector
I.4.5. Metode
Din corpul unei clase pot face parte i alte func ii: metodele. Exemplificarea o vom face tot pe
exemplul anterior.
Exemplul 61:
84
public class Copil
{
protected string nume; //data accesibila numai in interiorul
//clasei si a claselor derivate
public const int nr_max = 10; //constanta
public static int nr_copii = 0; //camp simplu (variabila)
static Copil[] copii = new Copil[nr_max]; //camp de tip
//tablou (variabila)
public static void adaug_copil(Copil c) //metod
{
copii[nr_copii++] = c;
if (nr_copii == nr_max)
throw new Exception("Prea multi copii");
}
public static void afisare() //metod
{
Console.WriteLine("Sunt {0} copii:", nr_copii);
for (int i = 0; i < nr_copii; i++)
Console.WriteLine("Nr.{0}. {1}", i + 1, copii[i].nume);
}
public Copil() //constructorul fara parametrii ai clasei
{
nume = Console.ReadLine();
}
...
Definirea datelor i metodelor nestatice corespunz toare clasei Copil i claselor derivate
Exemplul 62:
85
public class Copil
{
protected string nume;
...
...
}
class Fetita: Copil
{
public override void se_joaca( ) //redefinire
{
Console.WriteLine("{0} chinuie pisica.", this.nume);
}
}
...
//polimorfism
Fetita f = new Fetita( );
f.se_joaca("pisica");
f.se_joaca( );
Baiat b = new Baiat ( );
b.se_joaca("calculatorul");
b.se_joaca( );
I.4.6. Propriet i
Propriet ile sunt asem n toare cu metodele în ceea ce prive te modificatorii i numele
metodelor. Metodele de acces sunt dou : set i get. Dac proprietatea nu este abstract sau
extern , poate s apar una singur dintre cele dou metode de acces sau amândou , în orice
ordine.
Este o manier de lucru recomandabil aceea de a proteja datele membru (câmpuri) ale
clasei, definind instrumente de acces la acestea: pentru a ob ine valoarea câmpului respectiv (get)
sau de a memora o anumit valoare în câmpul respectiv (set). Dac metoda de acces get este
perfect asimilabil cu o metod ce returneaz o valoare (valoarea datei pe care vrem s-o ob inem
sau valoarea ei modificat conform unei prelucr ri suplimentare specifice problemei în cauz ),
metoda set este asimilabil cu o metod care un parametru de tip valoare (de intrare) i care
86
atribuie (sau nu, în func ie de context) valoarea respectiv câmpului. Cum parametrul
corespunz tor valorii transmise nu apare în structura sintactic a metodei, este de tiut c el este
implicit identificat prin cuvântul value. Dac se supune unor condi ii specifice problemei, se face o
atribuire de felul câmp=value.
Definirea în clasa Copil a propriet ii Nume, corespunz toare câmpului protejat ce re ine, sub
forma unui ir de caractere, numele copilului respectiv. Se va observ c proprietatea este
mo tenit i de clasele derivate Feti a i B iat.
Exemplul 63:
class Fetita:Copil
{
public override void se_joaca() //metoda get
{
Console.WriteLine("{0} leagana papusa.",this.Nume);
}
}
I.4.7. Concluzie
Scrierea unui program orientat obiect implic determinarea obiectelor necesare; acestea vor
realiza prelucr rile care definesc comportarea sistemului. Obiectele sunt responsabile pentru
modificarea datelor proprii.
87
5. implementarea claselor i a sistemului
6. testarea i punerea la punct.
I.5.1. Clase
O aplica ie C# este format din una sau mai multe clase, grupate în spa ii de nume -
namespaces. În mod obligatoriu, doar una dintre aceste clase con ine un punct de intrare - entry
point, i anume metoda Main.
Sintaxa:
[atribut][modificatorAcces] class
[identificator][:clasaBaza]
{
corpul_clasei
}
unde:
atribut – este op ional, reprezentând informa ii declarative cu privire la entitatea definit
modificatorAcces - este op ional, iar în cazul în care lipse te se consider public
modificatorAcces Explica ii
public acces nelimitat, clasa este vizibil peste tot
internal acces permis doar în clasa sau spa iul de nume care o cuprinde
protected acces în clasa curent sau în cele derivate
private modificator implicit. Acces permis doar pentru clase interioare
protected internal folosit pentru clase interioare semnificând accesul în clasa care-l
con ine sau în tipurile derivate din clasa care-l con ine
new permis claselor interioare. Clasa cu acest modificator ascunde un
membru cu acela i nume care este mo tenit
sealed clasa nu poate fi mo tenit
abstract clasa nu poate fi decât clas de baz , neputând fi instan iat . Se
folose te pentru clase interioare sau spa ii de nume
88
clasaBaza - este op ional, fiind numele clasei de baz , din care deriv clasa actual .
Exemplul 64: Se consider clasa IncludeClase care include ase clase având modificatori de
acces diferi i. Se pune problema „vizibilit ii” lor din exterior
using System;
using System.Collections.Generic;
using System.Text;
namespace AplicatiiClase
{
public class IncludeClase
{
public class Clasa1
{ }
abstract class Clasa2
{ }
protected class Clasa3
{ }
internal class Clasa4
{ }
private class Clasa5
{ }
class Clasa6
{ }
}
class Program
{
static void Main(string[] args)
{
IncludeClase.Clasa1 a;
IncludeClase.Clasa2 b; //Eroare,
//Clasa2 este inaccesibila
IncludeClase.Clasa3 c; //Eroare,
//Clasa3 este inaccesibila
IncludeClase.Clasa4 d;
IncludeClase.Clasa5 e; //Eroare,
//Clasa5 este inaccesibila
IncludeClase.Clasa6 f; //Eroare,
//Clasa6 este inaccesibila
}
}
}
Corpul clasei - este alc tuit din:
date
func ii
modificatorAcces Explica ii
public Membrul este accesibil de oriunde
internal Membrul este accesibil doar în assembly-ul curent (bloc
func ional al unei aplica ii .NET)
89
protected Membrul este accesibil oric rui membru al clasei care-l con ine i
a claselor derivate
private Modificator implicit. Accesibil permis doar pentru clasa care-l
con ine
protected internal Membrul este accesibil oric rui membru al clasei care-l con ine i
a claselor derivate, precum i în assembly-ul curent
I.5.1.(1) Date
Datele situate într-o clas sunt desemnate sub numele de variabile sau atribute. Datele pot
fi de orice tip, inclusiv alte clase.
unde:
Constantele - descriu valori fixe, putând fi valori calculate sau dependente de alte
constante. În mod obligatoriu valoarea unei astfel de constante trebuie s fie calculat în momentul
compil rii. Valoarea unei constante se declar prin cuvântul const. Sintaxa este:
unde tip poate fi: bool, decimal, sbyte, byte, short, ushort, int, uint, long,
ulong, char, float, double, enum, string
90
Constanta mai poate avea ca modificator de acces: new, public, protected,
internal, protected internal, private.
Exemplul 65:
class Constante
{ public const int MAX = 100;
const string SALUT = "Buna ziua!";
public const double MIN = MAX / 3.2;
}
Câmpul - reprezint o dat variabil a unei clase. În afar de modificatorii men iona i mai
sus, se mai adaug : new, readonly, volatile, static. Op ional, câmpurile pot fi ini ializate cu valori
compatibile. Un astfel de câmp se poate folosi fie prin specificarea numelui s u, fie printr-o
calificare bazat pe numele clasei sau al unui obiect. Sintaxa este:
Exemplul 66:
class Camp
{
public int varsta;
protected string nume;
private int id = 13;
int a; //implicit private
static void Main(string[] args)
{
Camp obiect = new Camp();
obiect.a = 1;
}
}
Câmpuri de instan
În cazul în care într-o declara ie de câmp nu este inclus modificatorul static, atunci
respectivul câmp se va reg si în orice obiect de tipul clasei curente care va fi instan iat. Deoarece
un astfel de câmp are o valoare specific fiec rui obiect, accesarea lui se va face folosind numele
obiectului:
obiect.a = 1;
91
Un câmp special este this care reprezint o referin la obiectul curent
Câmpuri statice
Dac într-o declara ie de câmp apare specificatorul static, câmpul respectiv va apar ine
clasei. Accesarea unui astfel de câmp din exteriorul clasei se poate face doar prin intermediul
numelui de clas :
Exemplul 67:
class Camp
{
public static int a = 13;
static void Main(string[] args)
{
Camp.a++;
}
}
Câmpuri readonly
Exemplul 68:
class Camp
{
public readonly string a = “Exemplu”; //camp readonly initializat
public readonly string b;
public class Camp(string b) //constructor
{this.b = b;} //camp readonly initializat
}
Câmpuri volatile
Câmpurile volatile se declar cu ajutorul cuvântului volatile, care poate fi ata at doar
urm toarelor tipuri:
byte, sbyte, short, ushort, int, uint, char, float, bool
92
un tip enumerare care are tipul: byte, sbyte, short, ushort, int, uint
un tip referin
tip valoare
numeric 0
bool false
char \0
enum 0
referin null
I.5.1.(2) Func ii
I.5.1.(3) Constructori
Defini ie: Constructorii sunt func ii care folosesc la ini ializarea unei instan e a clasei.
Constructorii au acela i nume cu al clasei. Constructorul poate avea un modificator de acces i nu
returneaz nimic. Sintaxa este:
modificatorAcces numeConstructor([parametri])[:initializator]
[{
corp_constructor
}]
93
unde:
initializator – permite invocarea unui constructor anume, înainte de executarea
instruc iunilor care formeaz corpul constructorului curent. Ini ializatorul poate lua dou forme:
base([parametri]) sau this([parametri]). Dac nu se precizeaz niciun ini ializator,
implicit se va asocia base( ).
În cazul în care nu definim nici un constructor, C# va crea unul implicit având corpul vid.
Exemplul 69:
class Elev
{
public Elev() //constructor
{
}
}
O clas poate con ine mai mul i constructori, diferen ia i dup num rul i tipul de parametri.
Exemplul 70:
class Elev
{
public string nume;
public Elev() //constructor
{
nume = "";
}
public Elev(string Nume) //constructor
{
nume = Nume;
}
}
Apelul unui constructor se face automat la instan ierea clasei prin operatorul new.
Exemplul 71:
class Exemplu_71
{
Elev elev = new Elev();
}
94
using System;
namespace Complex
{
class Complex
{
private int re;
private int im;
//constructor cu doi parametri
public Complex(int i, int j)
{
re = i;
im = j;
}
public void Afis()
{
Console.WriteLine(re + "+" + im + "i");
}
}
class Program
{
static void Main(string[] args)
{
Complex c = new Complex(1, 2);
c.Afis();
Console.ReadLine();
}
}
}
I.5.1.(4) Destructori
Exemplul 73:
95
using System;
using System.Collections.Generic;
using System.Text;
namespace Mesaj
{
class Program
{
static void Main(string[] args)
{
Mesaj a = new Mesaj();
Console.ReadLine();
}
class Mesaj
{
public Mesaj()
{
Console.WriteLine("Apel constructor");
}
~Mesaj()
{
Console.WriteLine("Apel destructor");
}
}
}
}
I.5.1.2.3. Metode
Metoda este un membru al unei clase care implementeaz o ac iune. Metoda poate admite
parametri i returna valori. Tipul returnat de c tre o metod poate fi unul predefinit (int, bool
etc.) sau de tip obiect (class). În cazul în care metoda nu returneaz nimic, tipul este void.
Metodele pot fi supradefinite (supraînc rcate), adic se pot defini mai multe metode, care s
poarte acela i nume, dar s difere prin num rul i tipul de parametri. Valoarea returnat de c tre o
metod nu poate s fie luat în considerare în cazul supradefinirii.
Sintaxa este:
unde:
modificatorAcces - este op ional. În cazul în care lipse te se consider implicit
96
private. modificatorAcces poate fi orice
modificatorAcces amintit, precum i new, static,
virtual, sealed, override, abstract, extern.
tipReturnat – poate fi un tip definit sau void.
numeMetoda - poate fi un simplu identificator sau, în cazul în care define te în mod explicit
un membru al unei interfe e, numele este de forma:
[numeInterfata].[numeMetoda]
parametri - lista de parametri formali este o succesiune de declar ri desp r ite prin virgule,
declararea unui parametru având sintaxa:
Modificatorul unui parametru poate fi ref (parametru de intrare i ie ire) sau out (parametru
care este numai de ie ire). Parametrii care nu au niciun modificator sunt parametri de intrare.
Semn tura fiec rei metode este format din numele metodei, modificatorii acesteia, num rul
i tipul parametrilor. Din semn tur (amprent ) nu fac parte tipul returnat, numele parametrilor
formali i nici specificatorii ref i out.
Numele metodei trebuie s difere de numele oric rui alt membru care nu este metod .
97
I.5.1.2.4. Propriet i
Sintaxa este:
unde:
tipReturnat - poate fi orice tip valid în C#, el specificând tipul folosit de accesorii get
(tipul valorii returnate) i set (tipul valorii atribuite).
Accesorul get corespunde unei metode f r parametri, care returneaz o valoare de tipul
propriet ii.
Accesorul set corespunde unei metode cu un singur parametru, de tipul propriet ii i tip de
retur void.
Dac proprietatea nu este abstract sau extern , poate s apar una singur dintre cele dou
metode de acces sau amândou , în orice ordine.
Este o manier de lucru recomandabil aceea de a proteja datele membru (câmpuri) ale
clasei, definind instrumente de acces la acestea: pentru a ob ine valoarea câmpului respectiv (get)
sau de a memora o anumit valoare în câmpul respectiv (set). Dac metoda de acces get este
perfect asimilabil cu o metod ce returneaz o valoare (valoarea datei pe care vrem s-o ob inem
sau valoarea ei modificat conform unei prelucr ri suplimentare specifice problemei în cauz ),
metoda set este asimilabil cu o metod care un parametru de tip valoare (de intrare) i care
atribuie (sau nu, în func ie de context) valoarea respectiv câmpului. Cum parametrul
98
corespunz tor valorii transmise nu apare în structura sintactic a metodei, este de tiut c el este
implicit identificat prin cuvântul value.
Exemplul 74:
using System;
using System.Collections.Generic;
using System.Text;
namespace GetSet
{
class ClasaMea
{
private int x;
public int P
{
get
{
Console.WriteLine("get");
return x;
}
set
{
Console.WriteLine("set");
x = value;
}
}
}
class Program
{
public static void Main(string[] args)
{
ClasaMea obiect = new ClasaMea();
obiect.P = 10;
Console.WriteLine(xVal);
Console.ReadLine();
}
}
}
99
I.5.1.(5) Evenimente i deleg ri
Evenimentele sunt membri ai unei clase ce permit clasei sau obiectelor clasei s fac
notific ri, adic s anun e celelalte obiecte asupra unor schimb ri petrecute la nivelul st rii lor.
Clasa furnizoare a unui eveniment public (pune la dispozi ia altor clase) acest lucru printr-o
declarare event care asociaz evenimentului un delegat, adic o referin c tre o func ie
necunoscut c reia i se precizeaz doar antetul, func ia urmând a fi implementat la nivelul claselor
interesate de evenimentul respectiv. Este modul prin care se realizeaz comunicarea între obiecte.
Sintaxa:
unde:
Un delegat se poate defini i în afara clasei generatoare de evenimente i poate servi i altor
scopuri în afara trat rii evenimentelor
100
Exemplul 75: dorim s definim o metod asociat unui vector de numere întregi, metod ce verific
dac vectorul este o succesiune cresc toare sau descresc toare. O implementare „generic ” se
poate realiza folosind deleg ri:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegari
{
public delegate bool pereche_ok(object t1, object t2);
public class Vector
{
public const int nmax = 4;
public int[] v = new int[nmax];
public Vector()
{
Random rand = new Random();
for (int i = 0; i < nmax; i++)
v[i] = rand.Next(0, 5);
}
public void scrie()
{
for (int i = 0; i < nmax; i++)
Console.Write("{0}, ", v[i]);
Console.WriteLine();
}
public bool aranj(pereche_ok ok)//ok e o delegare c tre o
//func ie necunoscut
{
for (int i = 0; i < nmax - 1; i++)
if (!ok(v[i], v[i + 1])) return false;
return true;
}
}
class Program
{
public static bool f1(object t1, object t2)
{
if ((int)t1 >= (int)t2) return true;
else return false;
}
public static bool f2(object t1, object t2)
{
if ((int)t1 <= (int)t2) return true;
else return false;
}
static void Main(string[] args)
{
Vector x;
do
{
x = new Vector(); x.scrie();
if (x.aranj(f1)) Console.WriteLine("Monoton descrescator");
if (x.aranj(f2)) Console.WriteLine("Monoton crescator");
} while (Console.ReadKey(true).KeyChar != '\x001B'); //Escape
}
}
}
101
Revenind la evenimente, descriem pe scurt un exemplu teoretic de declarare i tratare a unui
eveniment. În clasa Vector se consider c interschimbarea valorilor a dou componente ale unui
vector e un eveniment de interes pentru alte obiecte sau clase ale aplica iei. Se define te un tip
delegat TD (s zicem) cu ni te parametri de interes(de exemplu indicii componentelor
interschimbate) i un eveniment care are ca asociat un delegat E (de tip TD). Orice obiect x din clasa
Vector are un membru E (ini ial null). O clas C interesat s fie în tiin at când se face vreo
interschimbare într-un vector pentru a genera o anima ie (de exemplu), va implementa o metod M
ce realizeaz anima ia i va ad uga pe M (prin intermediul unui delegat) la x.E+=new
[tip_delegat](M). Cumulând mai multe astfel de referin e, x.E ajunge un fel de list de metode
(handlere). În clasa Vector, în metoda sort, la interschimbarea valorilor a dou componente se
invoc delegatul E. Invocarea lui E realizeaz de fapt activarea tuturor metodelor ad ugate la E.
I.5.1.(6) Indexatori
Sunt cazuri în care are sens s trat m o clas ca un array. Cei care au studiat C++ vor
observa c este o generalizare a supraînc rc rii operatorului [ ] din respectivul limbaj.
Sintaxa:
[atribut][modificatorIndexator] declaratorDeIndexator
{
declaratiiDeAccesor
}
unde:
modificatorIndexator – poate fi new, public, protected, internal, private,
virtual, sealed, override, abstract, extern.
102
declaratorDeIndexator – are forma:
unde:
listaParametrilorFormali – trebuie s con in cel pu in un parametru, parametru care nu trebuie s
fie de tipul ref sau out.
Observa ie: Indexatorii i propriet ile sunt asem n toare în ceea ce prive te utilizarea
accesorilor get i set. Un indexator poate fi privit ca o proprietate cu mai multe valori. Pe când o
proprietate poate fi declarat static , acest lucru este interzis în cazul indexatorilor.
Când folosim un indexator, sintaxa este asem n toare cu cea de la vectori. Totu i exist
deosebiri:
indexatorii pot folosi indici nenumerici, pe când un vector trebuie s aib indicii de tip întreg
indexatorii pot fi supradefini i, la fel ca metodele, pe când vectorii nu
indexatorii nu pot fi folosi i ca parametrii ref sau out, pe când vectorii da
Exemplul 76:
103
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_76
{
class ClasaMea
{
private string[] data = new string[6];
public string this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class Rezultat
{
public static void Main()
{
ClasaMea v = new ClasaMea();
v[0] = "Exemplu";
v[1] = "cu";
v[2] = "indexatori";
Console.WriteLine("{0} {1} {2}.", v[0], v[1], v[2]);
Console.ReadLine();
}
}
}
I.5.1.(7) Operatori
Defini ie: operatorul este un membru care define te semnifica ia unei expresii operator care
poate fi aplicat unei instan e a unei clase. Pentru cei care cunosc C++, operatorul corespunde
supraînc rc rii din respectivul limbaj.
Sintaxa:
104
Observa ia 3: În antetul unui operator nu poate ap rea, de mai multe ori, acela i
modificator.
Se pot declara operatori: unari, binari i de conversie.
Operatori unari
Supraînc rcarea operatorilor unari are urm toarea sintax :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_77
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
105
class Program
{
public static void Main()
{
Complex c1 = new Complex(10, 13);
c1.Afis();
Complex c2 = new Complex();
c2.Afis();
c2 = -c1;
c2.Afis();
Console.ReadLine();
}
}
Operatori binari
Operatorii binari supraînc rcabili sunt: + - * / & | ^ << >> == != > < >= <=
1. Cel pu in unul din cei doi parametri trebuie s fie de tipul clasei în care respectivul operator
a fost declarat
2. Operatorii de shift-are trebuie s aib primul parametru de tipul clasei în care se declar ,
iar al doilea parametru de tip int
3. Un operator binar poate returna orice tip
4. Urm torii operatori trebuie s se declare în pereche:
a. operatorii == i !=
b. operatorii > i <
c. operatorii >= i <=
Exemplul 78:
106
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ExempluOperatori
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void Afis()
{
Console.WriteLine("{0} {1}", x, y);
}
class Program
{
static void Main(string[] args)
{
Complex c1 = new Complex(1, 2);
Console.Write("c1: ");
c1.Afis();
Complex c2 = new Complex(3, 4);
Console.Write("c2: ");
c2.Afis();
Complex c3 = new Complex();
c3 = c1 + c2;
Console.WriteLine("\nc3 = c1 + c2\n");
Console.Write("c3: ");
c3.Afis();
Console.ReadLine();
}
}
}
Operatori de conversie
107
Operatorul de conversie introduce o conversie definit de utilizator. Aceast conversie nu va
suprascrie conversiile predefinite. Operatorii de conversie pot fi:
implici i – se efectueaz de la un tip ”mai mic” la un tip „mai mare” i reu esc întotdeauna,
nepierzându-se date
explici i – se efectueaz prin intermediul expresiilor de conversie, putându-se pierde date
Sintaxa:
Un operator de acest tip va face conversia de la tipul sursa (S) (tipul parametrului din antet)
în tipul destina ie (D) (tipul returnat).
O clas poate s declare un operator de conversie de la un tip S la un tip D dac :
1. S i D au tipuri diferite
2. S sau D este clasa în care se face definirea
3. S i D nu sunt object sau tip interfa
4. S i D nu sunt baze una pentru cealalt
Exemplu 79: conversii dintr-un tip de baz într-o clas i un tip clas într-un tip de baz folosind
conversia operator:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_79
{
class MyDigit
{
private int x;
public MyDigit()
{
}
public MyDigit(int i)
{
x = i;
}
public void ShowDigit()
{
Console.WriteLine("{0}", x);
}
public static implicit operator int(MyDigit md)
{
return md.x;
}
public static explicit operator MyDigit(int val)
{
return new MyDigit(val);
}
}
108
class Program
{
public static void Main(string[] args)
{
MyDigit md1 = new MyDigit(10);
int x = md1; //Implicit
Console.WriteLine(x);
int y = 25;
MyDigit md2 = (MyDigit)y; //Explicit
md2.ShowDigit();
Console.ReadLine();
}
}
}
Exemplul 80: Conversia dintr-un tip clas în altul folosind conversia operator:
109
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OperatoriImplicitiExpliciti
{
class Clasa1
{
public int x;
public Clasa1(int a)
{
x = a;
}
public void Afis1()
{
Console.WriteLine(x);
}
public static explicit operator Clasa2(Clasa1 mc1)
{
Clasa2 mc2 = new Clasa2(mc1.x * 10, mc1.x * 20);
return mc2;
}
}
class Clasa2
{
public float x, y;
public Clasa2(float a, float b)
{
x = a;
y = b;
}
public void Afis2()
{
Console.WriteLine(x);
Console.WriteLine(y);
}
}
class Program
{
public static void Main(string[] args)
{
Clasa1 mc1 = new Clasa1(100);
mc1.Afis1();
Clasa2 mc2 = (Clasa2)mc1;
mc2.Afis2();
Console.ReadLine();
}
}
}
110
I.6. Clase i func ii generice
Defini ie: genericele sunt abloane (templates) sau modele care ajut la reutilizarea
codului. Ele descriu clase i metode care pot lucra într-o manier uniform cu tipuri de valori
diferite.
Ele permit definirea de func ionalit i i metode care se adapteaz la tipurile parametrilor pe
care îi primesc, ceea ce permite construirea unui ablon.
Singura diferen fa de declararea în mod obi nuit a unei clase, este prezen a caracterelor
< i >, care permit definirea tipului pe care stiva îl va avea, ca i cum ar fi un parametru al clasei.
Tipurile generice (parametrizate) permit construirea de clase, structuri, interfe e, delega i sau
metode care sunt parametrizate printr-un tip pe care îl pot stoca sau manipula.
Exemplul 81: S consider m clasa Stiva care permite stocarea de elemente. Aceast clas are
dou metode Push() care permite introducerea de elemente i Pop() care permite extragerea de
elemente din stiv .
public class Stiva<TipElement> //clasa generica
{
private TipElement[] element;
111
interface IGeneric1<T>
{ }
class ClassGeneric1<UnTip, Altul>
{ }
class ClassInt1 : ClassGeneric1<int, int>
{ }
class ClassInt2<T> : ClassGeneric1<int, T>
{ }
class ClassInt3<T, U> : ClassGeneric1<int, U>
{ }
Exemplul 84: Dorim s implement m o clas Stiva care s permit ad ugarea i extragerea de
elemente. Pentru a simplifica problema, vom considera c stiva nu poate con ine decât un anumit
num r de elemente, ceea ce ne va permite s utiliz m tablouri în C#.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_84
{
class Stiva
{
private object[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new object[MAX_SIZE]; }
public Object Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}
112
public void Push(Object item)
{
if (m_Index == MAX_SIZE)
throw new StackOverflowException("Nu se poate adauga un
elemet: stiva este plina.");
m_ItemsArray[m_Index++] = item;
}
}
class Program
{
static void Main(string[] args)
{
Stiva stiva = new Stiva();
stiva.Push(1234);
int numar = (int)stiva.Pop();
}
}
}
Pentru a rezolva aceste neajunsuri s-ar putea implementa un cod pentru stive cu elemente
de tip int, alt cod pentru elemente de tip sir de caractere. Acest lucru duce la dublarea unor por iuni
din cod. Acest lucru se va rezolva cu ajutorul tipurilor generice.
113
Exemplul 85:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_85
{
class Stiva<T>
{
private T[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new T[MAX_SIZE]; }
public T Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}
public void Push(Object item)
{
if (m_Index == MAX_SIZE)
throw new StackOverflowException("Nu se poate adauga un
elemet: stiva este plina.");
m_ItemsArray[m_Index++] = item;
}
}
class Program
{
static void Main(string[] args)
{
Stiva<int> stiva = new Stiva<T>();
stiva.Push(1234);
int numar = stiva.Pop(); //nu mai este necesar cast
Stiva<string> sstiva = new Stiva<string>();
sstiva.Push("4321");
string sNumar = sstiva.Pop();
}
}
}
Prin utilizarea mo tenirii se poate defini o clas general care define te tr s turi comune la
un ansamblu de obiecte. Aceast clas poate fi mo tenit de c tre alte clase specifice, fiecare
dintre acestea ad ugând elemente care-i sunt unice ei.
114
O clas care este mo tenit se nume te clas de baz sau superclas , iar o clas care o
mo tene te pe aceasta se nume te clas derivat , sau subclas , sau clas descendent .
Pe baza a ceea ce am amintit, putem spune c o clas derivat este o versiune
specializat sau extins a clasei de baz .
Clasa derivat mo tene te toate elementele clasei de baz i- i adaug altele proprii.
Clasa derivat nu poate s tearg nici un membru al clasei de baz .
O clas derivat poate la rândul ei s fie clas de baz pentru o alt clas . În acest fel se
poate defini no iunea de ierarhie de clase.
Limbajul C#, spre deosebire de C++, admite doar mo tenirea simpl , în sensul c
derivarea se admite doar dintr-o clas de baz , fiind permis doar derivarea public
Exemplul 86:
115
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_86
{
class Muzician
{
public void Canta(string nume)
{
Console.WriteLine("{0} canta", nume);
}
}
class Violonist : Muzician
{
public void CantaLaVioara(string nume)
{
Console.WriteLine("{0} canta la vioara", nume);
}
}
class Program
{
static void Main(string[] args)
{
Muzician m = new Muzician();
m.Canta("Ilie");
Violonist n = new Violonist();
n.Canta("Andrei");
n.CantaLaVioara("Andrei");
Console.ReadLine();
}
}
}
Deseori, în procesul deriv rii, avem nevoie de acces la membrii mo teni i ai clasei de baz .
Pentru aceasta se va folosi o expresie de tip base access.
De exemplu, dac MembruB este un membru al clasei de baz , pentru a-l folosi într-o clasa
derivat vom folosi, în aceasta, o expresie de forma:
base.MembruB
116
Exemplul 84: apelul din clasa derivat a unui membru al clasei de baz
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_87
{
class Program
{
class ClasaDeBaza
{
public string sir = "Sir din clasa de baza";
}
Cuvântul cheie protected permite restrângerea accesului unui membru al clasei de baz
doar la clasele sale derivate. Membrii proteja i mo teni i devin în mod automat proteja i.
Exemplul 88:
117
class ClasaDeBaza
{
protected string var;
public ClasaDeBaza(string var) //constructor
{
this.var = var;
}
}
I.7.3. Metode
Prin mecanismul de mo tenire avem posibilitatea reutiliz rii codului i redefinirii (prin
polimorfism) a metodelor.
Exemplul 89:
118
class ClasaDeBaza
{
public virtual void Metoda()
{
...
}
}
class Derivata : ClasaDeBaza
{
public override void Metoda()
{
...
}
}
I.7.3.(2) new
Exist cazuri în care în loc s redefinim o metod avem nevoie s specific m c metoda
clasei derivate este o implementare nou a respectivei metode. Pentru aceasta vom folosi new cu
semnifica ia c metoda are aceea i signatur cu a celei din clasa de baz , dar dorim s masc m
definirea ei în clasa de baz .
Exemplul 90:
class ClasaDeBaza
{
public virtual void Metoda()
{
...
}
}
class Derivata : ClasaDeBaza
{
public new void Metoda()
{
...
}
}
I.7.4. Interfe e
Interfe ele sunt foarte importante în programarea orientat pe obiecte, deoarece permit
utilizarea polimorfismului într-un sens mai extins.
Defini ie: O interfa este o component a aplica iei, asem n toare unei clase, care declar
prin membrii s i (metode, propriet i, evenimente i indexatori) un „comportament” unitar aplicabil
mai multor clase, comportament care nu se poate defini prin ierarhia de clase a aplica iei.
De exemplu, dac vom considera arborele din figura urm toare, în care AVERE este o clas
abstract , iar derivarea claselor a fost conceput urm rind propriet ile comune ale componentelor
119
unei averi, atunci o clas VENIT nu este posibil , deoarece ea ar mo teni de la toate clasele
eviden iate, iar mo tenirea multipl nu este admis în C#.
AVERE
Proprietate Bani
Imobil VENIT
(din produse, din
De_folosin chirii, din dobânzi,
dividende)
calc()
I_inchiriat
Pentru metodele din cadrul unei interfe e nu se d nici o implementare, ci sunt pur i simplu
specificate, implementarea lor fiind furnizat de unele dintre clasele aplica iei. Acele clase care
„ader ” la o interfa spunem c „implementeaz ” interfa a respectiv . Nu exist instan iere în
cazul interfe elor, dar se admit deriv ri, inclusiv mo teniri multiple.
În exemplul nostru, se poate defini o interfa VENIT care s con in antetul unei metode
calc (s zicem) pentru calculul venitului ob inut, fiecare dintre clasele care implementeaz interfa a
VENIT fiind obligat s furnizeze o implementare (dup o formul de calcul specific ) pentru
metoda calc din interfa . Orice clas care dore te s adere la interfa trebuie s implementeze
toate metodele din interfa . Toate clasele care mo tenesc dintr-o clas care implementeaz o
interfa mo tenesc, evident, metodele respective, dar le pot i redefini (de exemplu, clasa
Credit_acordat redefine te metoda calc din clasa Investi ie, deoarece formula de calcul
implementat acolo nu i se „potrive te” i ei. Dac în sens polimorfic spunem c Investi ie este i
de tip Bani i de tip Avere, tot a a putem spune c o clas care implementeaz interfa a VENIT
i clasele derivate din ea sunt i de tip VENIT).
De exemplu, dac presupunem c toate clasele subliniate implementeaz interfa a
VENIT, atunci pentru o avere cu ac iuni la dou firme, un imobil închiriat i o depunere la banc ,
putem determina venitul total:
Exemplul 91:
120
Actiune act1 = new Actiune();
Actiune act2 = new Actiune();
I_inchiriat casa = new I_inchiriat();
Depunere dep=new Depunere();
Venit[] venituri = new Venit()[4];
venituri[0] = act1; venituri[1] = act2;
venituri[2] = casa; venituri[3] = dep;
...
int t=0;
for(i=0;i<4;i++)
t+=v[i].calc();
Defini ie: O excep ie este un obiect care încapsuleaz informa ii despre o situa ie anormal .
Excep ia se folose te pentru a semnala contextul în care apare acea situa ie deosebit
Observa ie: Nu trebuie confundat termenul de excep ie cu cel de eroare sau „bug”.
Excep iile nu sunt concepute pentru prevenirea bug-urilor. Chiar dac programatorul elimin toate
bug-urile din programul s u pot ap rea erori pe care el nu le poate preveni:
încercare de deschidere a unui fi ier inexistent
împ r iri la zero
etc.
În cazul în care o metod întâlne te o astfel de excep ie, atunci respectiva excep ie va
trebui „prins ” în vederea trat rii (rezolv rii) ei.
În C# se pot arunca ca excep ii obiecte de tip System.Exception sau derivate ale lui. Pe
lâng ierarhia de excep ii pe care limbajul C# o are inclus , programatorul î i poate crea propriile
sale tipuri excep ie.
Exception
SystemException
OutOfMemoryException
IOException
NullReferenceException
AplicationException
C# define te câteva excep ii standard derivate din System.Exception. Acestea sunt generate
când se produc erori la execu ia programului. Dintre acestea amintim:
Excep ia Explica ii
ArrayTypeMismatchException Incompatibilitate între tipul valorii
memorate i tipul tabloului
DivideByZeroException Încercare de împ r ire la zero
IndexOutOfRangeException Indexul tabloului dep e te marginile
definite
InvalidCastException Operatorul cast incorect la execu ie
OutOfMemoryException Datorit memoriei insuficiente apelul
lui new e ueaz
OverflowException Dep ire aritmetic
StackOverflowException Dep irea capacit ii (definite) stivei
Observa ie: Este posibil definirea de c tre programator a propriilor clase de excep ii.
Acestea vor fi derivate din ApplicationException.
122
I.8.1. Aruncarea i prinderea excep iilor
POO ofer o solu ie pentru gestionarea erorilor: folosirea blocurilor try i catch. În
scrierea codului, programatorul va separa acele instruc iuni care sunt sigure (adic nu pot fi
generatoare de excep ii), de cele care sunt susceptibile s conduc la erori. Partea de program
care poate genera excep ii o vom plasa într-un bloc try, iar partea corespunz toare trat rii
excep iei, într-un bloc catch.
În cazul în care blocul try genereaz o excep ie, Runtime întrerupe execu ia i caut un bloc
catch apropiat care, în func ie de tipul s u s poat trata respectiva eroare. În cazul în care este
g sit respectivul bloc catch programul continu cu instruc iunile din corpul catch. În cazul în care
nu se g se te nici un catch corespunz tor, execu ia programului este întrerupt .
Având în vedere c într-un corp try pot s apar excep ii diferite, în program pot exista mai
multe blocuri corespunz toare catch.
Exemplul 91:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exceptii1
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("Introduceti un numar ");
int i = int.Parse(Console.ReadLine());
Console.Write("Introduceti inca un numar ");
int j = int.Parse(Console.ReadLine());
int x = i / j;
}
catch (OverflowException e)
{
Console.WriteLine("Numarul nu este intreg"); //(1)
//Console.WriteLine(e); //(2)
}
123
/*
catch (DivideByZeroException e)
{
//Console.WriteLine(e); //(3)
Console.WriteLine("Exceptia DivideByZero"); //(4)
}*/
Console.WriteLine("Programul ruleaza in continuare");//(5)
}
}
}
Observa ie: Pentru a intercepta orice excep ii, indiferent de tipul lor se va folosi catch f r
parametru. Prin aceasta se va crea o rutin care va intercepta i trata toate excep iile.
unde:
NumeExceptie trebuie s fie numele unei clase apropiate de excep ia avut în vedere
excep ie – este un mesaj care apare în cazul în care apare excep ia, iar aceasta nu este
prins cu catch
124
Exemplul 92:
class Program
{
static void Main(string[] args)
{
try //(1)
{ //(2)
Console.Write("Introduceti o cifra ");
int i = int.Parse(Console.ReadLine());
if (i < 0 || i > 9)
{
string exceptie = i + " nu este o cifra"; //(0)
throw new ArgumentOutOfRangeException(exceptie);
}
} //(3)
catch (ArgumentOutOfRangeException) //(4)
{ //(5)
Console.WriteLine("Nu este cifra"); //(6)
} //(7)
Console.WriteLine("Programul ruleaza in continuare");
}
}
}
Dac vom comenta doar liniile aferente blocului catch (4), (5), (6), (7), apare un mesaj de
eroare privind faptul c se a teapt un bloc catch sau finally
Dac nici una dintre liniile programului nu este comentat , la rulare, chiar dac introduce un
num r în loc de o cifr vom ob ine:
125
I.8.1.(3) Blocul finally
Limbajul C# permite ca la ie irea dintr-un bloc try s fie executate obligatoriu, în cazul în
care programatorul dore te acest lucru, anumite instruc iuni. Pentru acest lucru, respectivele
instruc iuni vor fi plasate într-un bloc finally.
Blocul finally este util fie pentru a evita scrierea unor instruc iuni de mai multe ori, fie
pentru a elibera resursele dup p r sirea excep iei.
I.9. Polimorfism
I.9.1. Introducere
Pentru a permite acest mecanism, metodele care necesit o decizie contextual (în
momentul apelului), se declar ca metode virtuale (cu modificatorul virtual). În mod curent, în C#
modificatorului virtual al func iei din clasa de baz , îi corespunde un specificator override al
func iei din clasa derivat ce redefine te func ia din clasa de baz .
O metod ne-virtual nu este polimorfic i, indiferent de clasa c reia îi apar ine obiectul, va
fi invocat metoda din clasa de baz .
126
Limbajul C# admite trei tipuri de polimorfism:
polimorfism parametric
polimorfism ad-hoc
polimorfism de mo tenire
Exemplul 93: S consider m o func ie F cu un parametru formal, de tip vector, declarat folosind
modificatorul params. Acest lucru va permite folosirea mai multor parametri actuali, la apelul
func iei, prin intermediul acelui singur parametru formal.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_93
{
class Program
{
static void F(params int[] arg)
{
Console.WriteLine("Apelul functiei F cu {0} parametri:",
arg.Length);
for (int i = 0; i < arg.Length; i++)
{
Console.WriteLine("arg[{0}] = {1}", i, arg[i]);
}
Console.WriteLine("");
}
static void Main(string[] args)
{
F();
F(2);
F(4, 6);
F(new int[] { 1, 2, 3 });
}
}
}
127
I.9.3. Polimorfismul ad-hoc
Acest tip de polimorfism se mai nume te i supraînc rcarea metodelor. Prin acest mecanism
se pot defini în cadrul unei clase mai multe metode, toate având acela i nume, dar cu tipul i
num rul de parametri diferi i. La compilare, în func ie de parametri folosi i la apel, se va apela o
func ie sau alta.
Exemplul 94:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PolimorfismAdHoc
{
class Program
{
static void F()
{
Console.WriteLine("Functia F fara parametri\n");
}
static void F(int a, int b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
int\n");
}
static void F(int a, double b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
float\n");
}
static void Main(string[] args)
{
F();
F(2, 3);
F(4, 6.3);
}
}
}
128
I.9.4. Polimorfismul de mo tenire
În cazul acestui tip de mo tenire vom discuta într-o ierarhie de clase. În acest caz ne
punem problema apel rii metodelor, având aceea i list de parametri formali, metode ce
fac parte din clase diferite.
Exemplul 95:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exemplul_95
{
class Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}
129
S discut m despre prima linie afi at (cea de-a doua este evident ). Apelul lui Afis() se
rezolv în momentul compil rii pe baza tipului declarat al obiectelor. Deci linia (1) din program va
duce la apelul lui Afis() din clasa Baza, chiar dac obiect1 a fost instan iat pe baza unui obiect
din clasa Derivata.
namespace Exemplul_96
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public override void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}
130
I.9.6. Modificatorul new
În cazul în care se dore te ca o metod dintr-o clas derivat s aib aceea i semn tur cu
o metod dintr-o clas de baz , dar s nu fie considerat o suprascriere a ei, vom folosi
modificatorul new.
Exemplul 97:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PolimorfismDeMostenire
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public new void Afis() // !!! new
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}
131
I.9.7. Metoda sealed
O metod având tipul override poate fi declarat sealed. În acest fel ea nu mai poate fi
suprascris într-o clas derivat
Exemplul 98:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_98
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
sealed override public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Derivata2 : Derivata
{
override public void Afis() //!!! EROARE !!!
{
Console.WriteLine("Apelul functiei Afis din clasa Derivata2\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = new Derivata();
Derivata2 obiect3 = new Derivata2();
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
obiect3.Afis();
}
}
132
Va genera eroare, deoarece modificatorul sealed al metodei Afis(), din clasa Derivata, va
împiedic suprascrierea acestei metode în clasa Derivata2.
Programarea vizual trebuie privit ca un mod de proiectare a unui program prin operare
direct asupra unui set de elemente grafice (de aici vine denumirea de programare vizual ).
Aceast operare are ca efect scrierea automat a unor secven e de program, secven e care,
împreun cu secven ele scrise textual vor forma programul.
Spunem c o aplica ie este vizual dac dispune de o interfa grafic sugestiv i pune la
dispozi ia utilizatorului instrumente specifice de utilizare (drag, clic, hint etc.)
În realizarea aplica iei mai trebuie respectate i principiile proiect rii interfe elor:
Simplitatea: Interfa a trebuie s fie cât mai u or de în eles i de înv at de c tre utilizator
i s permit acestuia s efectueze opera iile dorite în timp cât mai scurt. În acest sens,
este vital culegerea de informa ii despre utilizatorii finali ai aplica iei i a modului în care
ace tia sunt obi nui i s lucreze.
Pozi ia controalelor: Loca ia controalelor dintr-o fereastr trebuie s reflecte importan a
relativ i frecven a de utilizare. Astfel, când un utilizator trebuie s introduc ni te
informa ii – unele obligatorii i altele op ionale – este indicat s organiz m controalele
astfel încât primele s fie cele care preiau informa ii obligatorii.
Consisten a: Ferestrele i controalele trebuie s fie afi ate dup un design asem n tor
(„template”) pe parcursul utiliz rii aplica iei. Înainte de a implementa interfa a, trebuie
decidem cum va ar ta aceasta, s definim „template”-ul.
Estetica: Interfa a trebuie s fie pe cât posibil pl cut i atr g toare.
133
II.2. Mediul de dezvoltare Visual C# (prezentarea interfe ei)
O aplica ie Windows con ine cel pu in o fereastr (Form) în care se poate crea o interfa cu
utilizatorul aplica iei.
Componentele vizuale ale aplica iei pot fi prelucrate în modul Designer (Shift+F7) pentru a
plasa noi obiecte, a le stabili propriet ile etc. Codul „din spatele” unei componente vizuale este
accesibil în modul Code (F7).
În fereastra Solution Explorer sunt afi ate toate fi ierele pe care Microsoft Visual C# 2008
Express Edition le-a inclus în proiect. Form1.cs este formularul creat implicit ca parte a proiectului.
Fi ierul Form1.cs con ine un formular (fereastra Form1 derivata din clasa Form) care este
reprezentat în cadrul din dreamt în formatul Design (Form1.cs[Design], adic într-un format in
134
care se poate executa proiectare vizual , prin inserarea controalelor necesare selectate din
fereastra Toolbox, care se activeaz atunci când este „atins ” cu mouse-ul.
Fi ierul Form1.cs poate fi v zut ca fi ier text surs prin selectarea lui în fereastra Solution
Explorer, clic dreapta cu mouse-ul i selec ia op iunii View Code.
Fereastra Properties (Ctrl+W,P) este utilizat pentru a schimba propriet ile obiectelor.
Toolbox (Ctrl+W,X) con ine controale standard drag-and-drop i componente utilizate în
crearea aplica iei Windows. Controalele sunt grupate în categoriile logice din imaginea al turat .
Ferestrele care sunt afi ate in fereastra principal se pot stabili prin selec ie din meniul View.
La crearea unei noi aplica ii vizuale, Microsoft Visual C# 2008 Express Edition genereaz un
spa iu de nume care con ine clasa static Program, cu metoda static ce constituie punctul de
intrare (de lansare) a aplica iei:
static void Main()
{ ...
Application.Run(new Form1());
}
Clasa Application este responsabil cu administrarea unei aplica ii Windows, punând la
dispozi ie propriet i pentru a ob ine informa ii despre aplica ie, metode de lucru cu aplica ia i
altele. Toate metodele i propriet ile clasei Application sunt statice. Metoda Run creeaz un
formular implicit, aplica ia r spunzând la mesajele utilizatorului pân când formularul va fi închis.
Compilarea modulelor aplica iei i asamblarea lor într-un singur fi ier „executabil” se
realizeaz cu ajutorul op iunilor din meniul Build, uzual fiind Build Solution (F6).
135
Odat implementat , aplica ia poate fi lansat , cu asisten de depanare sau nu (op iunile
Start din meniul Debug). Alte facilit i de depanare pot fi folosite prin um rirea pas cu pas,
urm rirea pân la puncte de întrerupere etc. (celelalte op iuni ale meniului Debug).
Ferestre auxiliare de urm rire sunt vizualizate automat în timpul procesului de depanare, sau
pot fi activate din submeniul Windows al meniului Debug.
Proiectarea vizual a formularului se poate face inserând controale selectate din fereastra de
instrumente (Toolbox) i setând propriet ile acestora.
În cele ce urmeaz pentru explica iile care vor avea loc vom considera o aplica ie Windows
numit Test:
136
Fereastra Toolbox Fereastra Windows Forms
Designer în care s-a creat Fereastra Solution
Form1 Explorer
Toate ferestrele, au în partea dreapt o piunez , care, dac este în pozi ie vertical
fixez fereastra deschis . În caz contrar fereastra se închide, retr gându-se în partea dreapt
sau stâng a mediului de programare.
Orice fereastr poate fi aranjat într-o pozi ie dorit de utilizator. Pentru aceasta d m clic
pe una dintre barele de titlu ale ferestrelor men ionale mai sus (Solution Explorer, Properties,
Toolbox sau Error List) si o deplas m în pozi ia dorit . În acest proces ve i fi ghidat de s ge ile
137
care apar central i pe margini. De preferat ar fi ca aceste ferestre s r mân în pozi iile lor
implicite.
Barele de instrumente
unde:
Icoana Semnifica ie
proiect nou (Ctrl+Shift+A)
138
Icoana Semnifica ie
cut (Ctrl+X)
copy (Ctrl+C)
paste (Ctrl+V)
Solution Configuration
Solution Platform
139
Icoana Semnifica ie
fereastra pentru c utare
A doua bar de instrumente se folose te atunci când dorim s ac ion m asupra mai multor
controale din fereastra noastr , i anume pentru: alinieri, spa ieri, redimension ri, aducerea în
fa /spate a unora dintre controalele existente. Icoanele aflate pe aceast bar sunt deosebit de
sugestive pentru ac iunea pe care o realizeaz .
Fereastra Toolbox
140
Fereastra Solution Explorer
Fereastra Properties
Aminteam mai sus c în Toolbox exist toate tipurile de controale care îi sunt necesare
unui programator pentru a realiza o aplica ie.
Cele mai multe controale sunt obiecte de clase derivate din clasa
System.Windows.Forms.Control. Datorit acestui fapt multe dintre propriet ile i
141
evenimentele diverselor controale vor fi identice. Vom vedea, în aplica iile care urmeaz , c exit
clase care definesc controale i care pot fi clase de baz pentru alte controale.
Fereastra Properties, din interfa a mediului de programare, vom observa c va con ine
atât propriet ile cât i evenimentele ata ate controalelor. Propriet ile controalelor, sunt
mo tenite sau supraînscrise din clasa de baz Control. Tabelul de mai jos prezint propriet ile
comune controalelor, propriet i furnizate de c tre clasa Control:
Aplica iile pe care le cre m trebuie s fie capabile, prin intermediul controalelor, s
sesizeze ac iunea utilizatorului asupra respectivelor controale. În func ie de tipul ac iunii vor
reac iona, printr-o secven de cod sau alta. Tot clasa Control amintit mai sus, implementeaz
i o serie de evenimente la care controalele vor reac iona:
142
Evenimentul Descrierea evenimentului
DragEnter se genereaz atunci când obiectul, printr-un drag and drop, ajunge în
interiorul controlului
DragLeave se genereaz atunci când obiectul, printr-un drag and drop, ajunge s
p r seasc controlului
DragOver se genereaz atunci când obiectul, printr-un drag and drop, ajunge
deasupra controlului
KeyDown se genereaz atunci când o tast este ap sat în timp ce controlul este
activ. Se va furniza codul ASCII al tastei ap sate. Se genereaz înainte
de evenimentele KeyPress i KeyUp
KeyPress se genereaz atunci când o tast este ap sat în timp ce controlul este
activ. Se va furniza codul de scanare al tastei ap sate. Se genereaz
dup KeyDown i înainte de KeyUp
KeyUp se genereaz când o tast este eliberat în timp ce controlul este activ.
Se genereaz dup KeyDown i KeyPress
GotFocus se genereaz când controlul devine activ (se mai spune: când controlul
prime te input focusul)
LostFocus se genereaz când controlul devine inactiv (se mai spune: când controlul
pierde input focusul)
MouseDown se genereaz când cursorul mouse-ului este deasupra controlului i se
apas un buton al mouse-ului
MouseMove se genereaz când trecem cu mouse-ul deasupra controlului
MouseUp se geereaz când mouse-ul este deasupra controlului i eliber m un
buton al mouse-ului
Paint se genereaz la desenarea controlului
Validated se genereaz când un control este pe cale s devin activ. Se genereaz
dup terminarea evenimentului Validating, indicând faptul c validarea
controlului este complet
Validating se genereaz când un control este pe cale s devin activ
II.4.1. Ferestre
Spa iul Forms ne ofer clase specializate pentru: creare de ferestre sau formulare
(System.Windows.Forms.Form), elemente specifice (controale) cum ar fi butoane
(System.Windows.Forms.Button), casete de text (System.Windows.Forms.TextBox) etc.
Proiectarea unei ferestre are la baz un cod complex, generat automat pe m sur ce noi
desemn m componentele i comportamentul acesteia. În fapt, acest cod realizeaz : derivarea
unei clase proprii din System.Windows.Forms.Form, clas care este înzestrat cu o colec ie de
controale (ini ial vid ). Constructorul ferestrei realizeaz instan ieri ale claselor Button, MenuStrip,
Timer etc. (orice plas m noi în fereastr ) i adaug referin ele acestor obiecte la colec ia de
controale ale ferestrei.
143
Dac modelul de fereastr reprezint ferestra principal a aplica iei, atunci ea este
instan iat automat în programul principal (metoda Main). Dac nu, trebuie s scriem noi codul
care realizeaz instan ierea.
Clasele derivate din Form mo tenesc o serie de propriet i care determin atributele vizuale
ale ferestrei (stilul marginilor, culoare de fundal, etc.), metode care implementeaz anumite
comportamente (Show, Hide, Focus etc.) i o serie de metode specifice (handlere) de tratare a
evenimentelor (Load, Click etc.).
Formularul deschis modal va avea un proprietar setat pe null. De in torul se poate stabili
setând proprietarul înainte s apel m Form.ShowDialog() sau apelând From.ShowDialog() cu
proprietarul ca argument.
Vizibilitatea unui formular poate fi setat folosind metodele Hide sau Show. Pentru a
ascunde un formular putem folosi :
144
Printre cele mai uzuale propriet i ale form-urilor, reamintim:
StartPosition determin pozi ia ferestrei atunci când aceasta apare prima dat . Pozi ia poate fi
setat Manual, sau poate fi centrat pe desktop (CenterScreen), stabilit de Windows,
formularul având dimensiunile i loca ia stabilite de programator (WindowsDefaultLocation)
sau Windows-ul va stabili dimensiunea ini ial i loca ia pentru formular
(WindowsDefaultBounds) sau, centrat pe formularul care l-a afi at (CenterParent) atunci
când formularul va fi afi at modal.
Location (X,Y) reprezint coordonatele col ului din stânga sus al formularului relativ la col ul
stânga sus al containerului. (Aceast propietate e ignorat dac StartPosition = Manual).
Mi carea formularului ( i implicit schimbarea loca iei) poate fi tratat în evenimentele Move i
LocationChanged .
Loca ia formularului poate fi stabilit relativ la desktop astfel:
void Form_Load(object sender, EventArgs e) {
this.Location = new Point(1, 1);
this.DesktopLocation = new Point(1, 1);
} //formularul in desktop
Size (Width i Height) reprezint dimensiunea ferestrei. Când se schimb propiet ile Width i
Height ale unui formular, acesta se va redimensiona automat, aceast redimensionare fiind
tratat în evenimentele Resize sau in SizeChanged. Chiar dac propietatea Size a
formularului indic dimensiunea ferestrei, formularul nu este în totalitate responsabil pentru
desenarea întregului con inut al s u. Partea care este desenat de formular mai este denumit
i Client Area. Marginile, titlul i scrollbar-ul sunt desenate de Windows.
MaxinumSize i MinimumSize sunt utilizate pentru a restric iona dimensiunile unui formular.
void Form_Load(object sender, EventArgs e) {
this.MinimumSize = new Size(200, 100);...
this.MaximumSize = new Size(int.MaxValue, 100);...}
ControlBox precizeaz dac fereastra con ine sau nu un icon, butonul de închidere al ferestrei
i meniul System (Restore,Move,Size,Maximize,Minimize,Close).
145
ShowInTaskbar precizeaz dac fereastra apare in TaskBar atunci când formularul este
minimizat.
SizeGripStyle specific tipul pentru ‘Size Grip’ (Auto, Show, Hide). Size grip (în col ul din
dreapta jos) indic faptul c aceast fereastr poate fi redimensionat .
TopMost precizeaz dac fereastra este afisat în fa a tuturor celorlalte ferestre.
TransparencyKey identific o culoare care va deveni transparent pe form .
Definirea unei func ii de tratare a unui eveniment asociat controlului se realizeaz prin
selectarea grupului Events din ferestra Properties a controlului respectiv i alegerea eveni-
mentului dorit.
Dac nu scriem nici un nume pentru func ia de tratare, ci efectu m dublu clic în c su a
respectiv , se genereaz automat un nume pentru aceast func ie, inând cont de numele
controlului i de numele evenimentului (de exemplu button1_Click).
II.4.2. Controale
Unitatea de baz a unei interfe e Windows o reprezint un control. Acesta poate fi „g zduit”
de un container ce poate fi un formular sau un alt control.
146
Controale form. Controlul form este un container. Scopul s u este de a g zdui alte controale.
Folosind propriet ile, metodele i evenimentele unui formular, putem personaliza programul
nostru.
În tabelul de mai jos ve i g si o list cu controalele cel mai des folosite i cu descrierea lor.
Exemple de folosire a acestor controale vor urma dup explicarea propriet ilor comune al
controalelor i formularelor.
II.5. Aplica ii
Cu ajutorul metodei Drag and drop plasa i pe formular un buton pe care ve i introduce textul
START, dou controale TextBox, dou controale label pe care ve i introduce textele din exemplul
de mai jos
147
Executa i dublu clic pe butonul START i edita i codul surs conform exemplului de mai jos:
În acest moment aplica ia este gata. Din meniul File alege i op iunea Save All i rula i
aplica ia.
148
II.5.2. Propriet i comune ale controalelor i formularelor:
Proprietatea Text Aceast proprietate poate fi setat în timpul proiect rii din fereastra
Properties, sau programatic, introducând o declara ie în codul programului.
public Form1(){
InitializeComponent();
this.Text = "Primul formular";
}
Propriet ile ForeColor i BackColor. Prima proprietate enun at seteaz culoare textului din
formular, iar cea de a doua seteaz culoarea formularului. Toate acestea le pute i modifica
dup preferin e din fereastra Properties.
Proprietatea BorderStyle. Controleaz stilul bordurii unui formular. Încerca i s vede i cum se
modific setând proprietatea la Fixed3D (tot din fereastra Properties).
Proprietatea FormatString v permite s seta i un format comun de afi are pentru toate
obiectele din cadrul unei ListBox. Aceasta se g se te disponibil în panoul Properties.
Proprietatea AutoCheck când are valoarea true, un buton radio î i va schimba starea
automat la executarea unui clic.
Proprietatea AutoSize folosit la controalele Label i Picture, decide dac un control este
redimensionat automat, pentru a-i cuprinde întreg con inutul.
149
Proprietatea Enabled determin dac un control este sau nu activat într-un formular.
Proprietatea TabIndex seteaz sau returneaz pozi ia controlului în cadrul aranj rii taburilor.
Când dezvolt m programe pentru Windows, uneori trebuie s afi m ferestre adi ionale. De
asemenea trebuie s le facem s dispar de pe ecran. Pentru a reu i acest lucru folosim
metodele Show() i Close() ale controlului. Cel mai important eveniment pentru Button este
Clic (desemnând ac iunea clic stânga pe buton).
Deschide i o nou aplica ie Windows Forms, trage i un control de tip Button pe formular.
Din meniul Project selecta i Add Windows Form, iar în caseta de dialog care apare ad uga i
numele Form2, pentru noul formular creat. În acest moment a i inclus în program dou formulare.
Trage i un buton în Form2 i executa i dublu clic pe buton, pentru a afi a administratorul s u de
evenimente. Introduce i acum în el linia de cod this.Close();.
Numele metodei button1_Clic este alc tuit din numele controlului button1, urmat de
numele evenimentului: Clic.
150
Acum ar trebui s reveni i la Form1 i executa i dublu clic pe butonul din acest formular
pentru a ajunge la administratorul s u de evenimente. Edita i administratorul evenimentului
conform exemplului de mai jos:
În acest moment rula i programul ap sând tasta F5 i ve i observa c la executarea unui clic
pe butonul din Form1 se deschide Form2 iar la executarea unui clic pe butonul din Form2 acesta
se închide.
Exemplul 3: Imagini
Deschide i o nou aplica ie Windows Forms, trage i dou controale de tip Button pe
formular pe care le redenumi i cu DA i cu NU, un control de tip PictureBox i un control de tip
Label pe care scrie i textul: Te crezi inteligent?.
Textul pentru fiecare control îl ve i introduce utilizând proprietatea Text. Va trebui sa ave i
dou imagini diferite salvate într-un folder pe calculatorul vostru.
Executa i dublu clic pe butonul DA i folosi i urm torul cod pentru administratorul
evenimentului Clic:
151
private void button1_Click(object sender, EventArgs e)
{pictureBox1.Image = Image.FromFile("C:\\Imagini \\line.gif");
pictureBox1.Visible = true;}
Va trebui s completa i corect calea spre folder-ul în care a i salvat imaginea pentru importul
cu succes al ei.
Executa i dublu clic pe butonul NU i folosi i urm torul cod pentru administratorul
evenimentului Clic:
Ve i ob ine la rularea aplica iei afi area uneia din cele dou imagini, în func ie de butonul ap sat.
sau
Tot în cadrul evenimentului Clic, oferim acum un exemplu de afi are într-un TextBox a unui
mesaj, în momentul în care se execut clic pe un buton. Deschide i o nou aplica ie Windows
Forms. Trage i un control de tip Button pe formular i un control de tip TextBox. Modifica i textul ce
apare pe buton, conform imaginii, i executa i dublu clic pe el, pentru a ajunge la administratorul
s u de evenimente. Modifica i codul surs al controlului Button, conform exemplului de mai jos.
152
Exemplul 5: Caset de mesaj
Exemplul 6:
Solu ia unei probleme cu mai multe variante de r spuns este memorat cu ajutorul unor
checkbox-uri cu proprietatea ThreeState. Ap sarea butonului Verific determin afi area unei
etichete i a butoanelor radio DA i NU. R spunsul este afi at într-un MessageBox.
153
Dup ad ugarea controalelor pe formular i setarea propriet ilor Text i ThreeState în
cazul checkbox-urilor stabilim evenimentele clic pentru butonul Verifica i pentru butonul radio cu
eticheta DA:
154
Executând dublu clic pe butonul Start va fi deschis codul surs . În func ia button1_Clic
ini ializ m variabila m cu valoarea 1 i pornim timer-ul.
În aceea i fereastr de cod scriem func ia recursiv patrat care va genera fractalul.
if (n > 1)
{
patrat(n - 1, x - l4, y - l4, l2);
patrat(n - 1, x - l4, y + l3, l2);
patrat(n - 1, x + l3, y - l4, l2);
patrat(n - 1, x + l3, y + l3, l2);
}
Graphics graph = this.CreateGraphics();
Pen penc;
if (n % 2 == 0) penc = new Pen(Color.Red);
else penc = new Pen(Color.BlueViolet);
Point[] p = new Point[4];
p[0].X = x; p[0].Y = y;
p[1].X = x; p[1].Y = y + l;
p[2].X = x + l; p[2].Y = y + l;
p[3].X = x + l; p[3].Y = y;
graph.DrawPolygon(penc, p);
}
155
Se execut acum dublu clic pe obiectul timer de pe formular pentru a completa func ia
timer1_Tick cu apelul func iei recursive patrat.
În acest moment aplica ia este gata. Din meniul File alege i op iunea Save All i rula i
aplica ia.
156
Crea i o nou aplica ie Windows Forms, apoi trage i un buton în formular i seta i
proprietatea Text a butonului la : „s avem un dialog”, iar apoi executa i dublu clic pe buton i
modifica i numele metodei din button1_click în button1_MouseEnter apoi folosi i urm torul
cod pentru administratorul evenimentului MouseEnter.
astfel:
Crea i un alt formular la acest proiect (alege i Add Windows Forms din meniul Project), apoi
în ordine: seta i proprietatea ControlBox la valoarea false, seta i proprietatea Text la “caset de
dialog”, trage i în formular un control de tip Label i seta i proprietatea Text la “scrie text”, ad uga i
un control TextBox în formular, ad uga i dou controale de tip Button, seta i proprietatea Text a
butonului din stânga la “OK” iar al celui din dreapta la “Cancel”, seta i proprietatea DialogResult a
butonului din stanga la OK iar al celui din dreapta la Cancel, executa i clic pe formularul casetei de
dialog i seta i proprietatea AcceptButton la button1 iar proprietatea CancelButton la button2.
Acum executa i dublu clic pe butonul OK i folosi i urm torul cod pentru administratorul
evenimentului Clic:
Executa i dublu clic pe butonul Cancel i folosi i urm torul cod pentru administratorul
evenimentului Clic:
157
La începutul clasei Form2 ad uga i declara ia: public string textBoxText; iar la
sf r itul clasei Form2 ad uga i proprietatea:
În acest exemplu este prezentat modalitatea de schimbare aleatoare a culorii unei etichete.
Se deschide o aplica ie Windows Forms pe care o ve i denumi Schimb culoarea. Din fereastra
Properties redenumi i formularul. Stabili i dimensiunea formularului i culoarea de fond alegând
una dintre cele predefinite din op iunea BackColor.
Cu ajutorul metodei Drag and drop plasa i pe formular: un control de tip Button pe care ve i
introduce textul START, un control de tip Button pe care ve i introduce textul STOP, un control de
tip Label pe care ve i introduce textul Schimb culoarea, un control de tip Timer.
158
Executa i dublu clic pe butonul START i edita i administratorul evenimentului conform
exemplului de mai jos:
astfel:
Declara i urm toarea variabil ca fiind variabil local pentru clasa Form1
Executa i dublu clic pe controlul Timer i insera i linia de cod care va permite schimbarea
aleatoare a culorilor pentru controlul Label conform exemplului de mai jos:
În acest moment aplica ia este gata. Din meniul File alege i op iunea Save All i rula i
aplica ia.
159
Exemplul 10: Trei culori
Acest exemplu afi eaz un grup alc tuit din 3 butoane, etichetate A,B respectiv C având
ini ial culoarea ro ie. Ap sarea unui buton determin schimbarea culorii acestuia în galben. La o
nou ap sare butonul revine la culoare ini ial . Ac ionarea butonului „Starea butoanelor” determin
afi area într-o caset text a etichetelor butoanelor galbene. Caseta text devine vizibil atunci când
ap s m prima oar acest buton. Culoarea butonului mare (verde/portocaliu) se schimb atunci
când mouse-ul este pozi ionat pe buton. Dup ad ugarea butoanelor i a casetei text pe formular,
stabilim evenimentele care determin schimbarea culoriilor i completarea casetei text.
160
i
LinkLabel afi eaz un text cu posibilitatea ca anumite p r i ale textului (LinkArea) s fie
desenate ca i hyperlink-uri. Pentru a face link-ul func ional trebuie tratat evenimentul LinkCliced.
În acest exemplu, prima etichet permite afi area con inutului discului C:, a doua leg tur
este un link c tre pagina www.microsoft.com/romania i a treia acceseaz Notepad.
161
private void linkLabel1_LinkCliced (object sender,
LinkLabelLinkClicedEventArgs e )
{ linkLabel1.LinkVisited = true;
System.Diagnostics.Process.Start( @"C:\" );}
private void linkLabel2_LinkCliced( object sender,
LinkLabelLinkClicedEventArgs e )
{ linkLabel2.LinkVisited = true;
System.Diagnostics.Process.Start("IExplore",
"http://www.microsoft.com/romania/" );}
private void linkLabel3_LinkCliced( object sender,
LinkLabelLinkClicedEventArgs e )
{ linkLabel3.LinkVisited = true;
System.Diagnostics.Process.Start( "notepad" );}
Executa i dublu clic pe controlul timer i completa i func ia timer1_Tick conform modelului
de mai jos:
162
private void timer1_Tick(object sender, EventArgs e)
{ double u = 2 * i * Math.PI / 100;
v[0].X = cx / 2 + cx / 2 * (float)Math.Cos(u);
v[0].Y = 5 * cy / 8 + cy / 16 * (float)Math.Sin(u);
v[1] = new PointF(cx / 2, -cy);v[2] = new PointF(cx / 2, 2 * cy);
u += Math.PI / 4;v[3].X = cx / 2 + cx / 4 * (float)Math.Cos(u);
v[3].Y = cy / 2 + cy / 16 * (float)Math.Sin(u);
Pen p = new Pen(Color.FromArgb(r.Next(2), r.Next(200), r.Next(2)));
graf.DrawBeziers(p, v);
i++;
}
În acest moment aplica ia este gata. Din meniul File alege i op iunea Save All i rula i
aplica ia.
Metoda Dispose()
Exemplul 13:
163
Se adaug pe un formular dou butoane i o caset text. Ap sarea primului buton va
determina afi area textului din TextBox într-un MessageBox iar ap sarea celui de-al doilea buton
va închide aplica ia (metoda Dispose() va închide aplica ia).
Dup ad ugarea celor dou butoane i a casetei text a fost schimbat textul afi at pe cele
dou butoane au fost scrise func iile de tratare a evenimentului Clic pentru cele dou butoane:
164
void button1_Click(object source, System.EventArgs e)
{ String s = "Am selectat si am adaugat itemii: ";
listBox1.Items.Clear();
foreach ( object c in checkedListBox1.CheckedItems)
{listBox1.Items.Add(c);
s = s + c.ToString();s = s + " ";
}
label1.Text = s;
}
Exemplul 15: este un exemplu de utilizare a controlului ListView. ListView este folosit pentru a
afi a o colec ie de elemente în unul din cele 4 moduri (Text, Text+Imagini mici, Imagini mari,
Detalii). Acesta este similar grafic cu ferestrele în care se afi eaz fi ierele dintr-un anumit director
din Windows Explorer. Fiind un control complex, con ine foarte multe propriet i, printre care:
View ( selecteaz modul de afi are (LargeIcon, SmallIcon, Details, List)),
LargeImageList, SmallImageList (icon-urile de afi at în modurile LargeIcon, SmallIcon),
Columns (utilizat doar în modul Details, pentru a defini coloanele de afi at), Items (elementele
de afi at).
Exemplul acesta afi eaz într-un ListView o list de elevi. Clasa Elev con ine i o metod
static ce returneaz o list de elevi (ne putem imagina c lista respectiv e citit din baza de
date), este aceasta:
class Elev
{
public string Nume { get; set; }
public string Prenume { get; set; }
public int Nota { get; set; }
public static List<Elev> CitesteElevi()
{
List<Elev> elevi = new List<Elev>();
elevi.Add(new Elev() { Nume = "Nume 1", Prenume = "Prenume 1",
Nota = 9 });
elevi.Add(new Elev() { Nume = "Nume 2", Prenume = "Prenume 2",
Nota = 10 });
elevi.Add(new Elev() { Nume = "Nume 3", Prenume = "Prenume 3",
Nota = 8 });
elevi.Add(new Elev() { Nume = "Nume 4", Prenume = "Prenume 4",
Nota = 9 });
return elevi;
}
}
165
Proiectul nostru con ine i un Form unde am a ezat un control de tip ListView. Codul din
Form1.cs este acesta:
public Form1()
{
InitializeComponent();
SeteazaLista();
}
private void SeteazaLista()
{
listViewTest.Columns.Add("Nume", 200, HorizontalAlignment.Left);
listViewTest.Columns.Add("Prenume", 200,
HorizontalAlignment.Left);
listViewTest.Columns.Add("Nota", 200, HorizontalAlignment.Left);
listViewTest.View = View.Details;
listViewTest.Sorting = SortOrder.Ascending;
listViewTest.AllowColumnReorder = true;
}
private void Form1_Load(object sender, EventArgs e)
{
this.listViewTest.BeginUpdate();
ListViewItem lvi;
ListViewItem.ListViewSubItem lvsi;
foreach (Elev elev in Elev.CitesteElevi())
{
lvi = new ListViewItem();
lvi.Text = elev.Nume;
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = elev.Prenume;
lvi.SubItems.Add(lvsi);
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = elev.Nota.ToString();
lvi.SubItems.Add(lvsi);
listViewTest.Items.Add(lvi);
}
this.listViewTest.EndUpdate();
}
}
Metoda SeteazaLista preg te te lista pentru datele care îi vor fi servite: mai înt i îi adaug 3
coloane, iar apoi seteaz propriet i care in de modul de afo are al acesteia. La Form1_Load
(adic atunci când form-ul se încarc ) se vor lega datele (lista de elevi) de controlul de interfa .
166
Metoda Draw()
Exemplul 16: Aplica ia este un exemplu de utilizare a controlului ImageList. Acesta este un control
care con ine o list de imagini, care poate fi setat la design (proprietatea Collection):
Controlul ImageList dispune de o metod care permite desenarea imaginilor pe care le con ine.
Iat exemplul (metod executat la clic pe un buton):
167
Evenimentul DateSelected
MonthCalendar afi eaz un calendar prin care se poate selecta o dat (zi, luna, an) în mod
grafic. Propriet ile mai importante sunt: MinDate, MaxDate, TodayDate ce reprezint data
minim /maxim selectabil i data curent (care apare afi at diferen iat sau nu în func ie de
valorile propriet ilor ShowToday,ShowTodayCircle.
Formularul din aplica ie con ine un calendar pentru care putem selecta un interval de
maximum 30 de zile, sunt afi ate s pt mânile i ziua curent . Intervalul selectat se afi eaz prin
intermediul unei etichete. Dac se selecteaz o dat atunci aceasta va fi ad ugat ca item într-un
ComboBox (orice dat poate ap rea cel mult o dat în list ).
Dup ad ugarea celor 3 controale pe formular, stabilim propriet ile pentru monthCalendar1
(ShowWeekNumber-True, MaxSelectionCount-30, etc.) i preciz m ce se execut atunci când
select m un interval de timp:
168
Evenimentele MouseDown, MouseUp, MouseMove
Grupuri de controale Toolbar (ToolStrip) afi eaz o bar de butoane în partea de sus a unui
formular. Se pot introduce vizual butoane (printr-un designer, direct din Visual Studio.NET IDE), la
care se pot seta atât textul afi at sau imaginea. Evenimentul cel mai util al acestui control este
ButtonClic (care are ca parametru un obiect de tip ToolBarButtonClicEventArgs, prin care
programatorul are acces la butonul care a fost ap sat).
În aplica ia urm toare cele 3 butoane ale toolbar-ului permit modificarea propriet ilor
textului introdus în caset . Toolbar-ul se poate muta f r a dep i spa iul ferestrei. Schimbarea
fontului se realizeaz cu ajutorul unui control FontDialog(), iar schimbarea culorii utilizeaz
ColorDialog().
169
private void toolBar1_MouseDown(object sender, MouseEventArgs e)
{ // am apasat butonul de mouse pe toolbar
am_apasat = true;
forma_deplasata = new Point(e.X, e.Y); toolBar1.Capture = true;}
Metoda ShowDialog()
170
Exemplul permite, prin intermediul unui meniu, scrierea unui fi ier Notpad, afi area
continutului acestuia într-o caset text, schimbarea fontului i culorii de afi are, tergerea con inutului
casetei, afi area unor informa ii teoretice precum i Help dinamic. Au fost definite chei de acces
rapid pentru accesarea componentelor meniului.
File New permite scrierea unui fi ier notepad nou
System.Diagnostics.Process.Start( "notepad" );
File Open selecteaz i afi eaz în caseta text con inutul unui fi ier text.
File Close terge con inutul casetei text, File Exit închide aplica ia
Window Font i Window Color permit stabilirea fontului/culorii textului afi at.
Help DinamicHelp acceseaz
System.Diagnostics.Process.Start("IExplore",
"http://msdn2.microsoft.com/en-us/default.aspx");
Help About PV afi eaz în caseta text informa ii despre implementarea unui meniu.
171
II.5.4. Obiecte grafice
Spa iul System.Drawing con ine tipuri care permit realizarea unor desene 2D i au rol
deosebit în proiectarea interfe elor grafice.
Un obiect de tip Point este reprezentat prin coordonatele unui punct într-un spa iul
bidimensional
Exemplu:
Point este utilizat frecvent nu numai pentru desene, ci i pentru a identifica în program un
punct dintr-un anumit spa iu. De exemplu, pentru a modifica pozi ia unui buton în fereastr putem
asigna un obiect de tip Point propriet ii Location indicând astfel pozi ia col ului din stânga-sus
al butonului
Exemplu:
button.Location = new Point(100, 30);
Structura Color con ine date, tipuri i metode utile în lucrul cu culori. Fiind un tip valoare
(struct) i nu o clas , aceasta con ine date i metode, îns nu permite instan iere, constructori,
destructor, mo tenire.
Clasa Graphics este o clas sigilat reprezentând o arie rectangular care permite
reprezent ri grafice. De exemplu, o linie frânt se poate realiza astfel:
172
Point[] points = new Point[4];
points[0] = new Point(0, 0);points[1] = new Point(0, 120);
points[2] = new Point(20, 120);points[3] = new Point(20, 0);
Graphics g = this.CreateGraphics();
Pen pen = new Pen(Color.Yellow, 2);g.DrawLines(pen, points);
Aplica ia este un exerci iu care deseneaz cercuri de raze i culori aleatoare i emite
sunete cu frecven aleatoare.
Image thumbnail;
private void Thumbnails_Load(object sender, EventArgs e)
{ try{Image img = Image.FromFile("C:\\Imagini\\catel.jpg");
int latime=100, inaltime=100;
thumbnail=img.GetThumbnailImage(latime, inaltime,null, IntPtr.Zero);}
catch{MessageBox.Show("Nu exista fisierul");}
}
private void Thumbnails_Paint(object sender, PaintEventArgs e)
{e.Graphics.DrawImage(thumbnail, 10, 10);}
173
II.5.5. Validarea informa iilor de la utilizator
Înainte ca informa iile de la utilizator s fie preluate i transmise c tre alte clase, este
necesar s fie validate.
Acest aspect este important, pentru a preveni posibilele erori. Astfel, dac utilizatorul
introduce o valoare real (float) când aplica ia a teapt un întreg (int), este posibil ca aceasta s
se comporte neprev zut abia câteva secunde mai târziu, i dup multe apeluri de metode, fiind
foarte greu de identificat cauza primar a problemei.
Datele pot fi validate pe m sur ce sunt introduse, asociind o prelucrare unuia dintre
handlerele asociate evenimentelor la nivel de control (Leave, Textchanged, MouseUp etc.)
În unele situa ii (de exemplu atunci când valorile introduse trebuie s se afle într-o anumit
rela ie între ele), validarea se face la sfâr itul introducerii tuturor datelor la nivelul unui buton final
sau la închiderea ferestrei de date.
174
private void btnValidate_Click(object sender, System.EventArgs e)
{ foreach(System.Windows.Forms.Control a in this.Controls)
{ if( a is System.Windows.Forms.TextBox & a.Text=="")
{ a.Focus();return;}
}
}
II.5.5.(3) ErrorProvider
O manier simpl de a semnala erori de validare este aceea de a seta un mesaj de eroare
pentru fiecare control .
II.5.6. MessageBox
Pe fereastra care apare la ini ializarea proiectului nostru, vom plasa un buton pe care
scriem: “APASATI”. D m dublu clic pe respectivul buton i scriem codul în func ia generat de
aceast ac iune:
MessageBox.Show("BUNA ZIUA!");
175
S analiz m pu in codul nostru, aducându-ne aminte de no iunile de programare orientat
obiect studiate:
În momentul în care se apas butonul OK, fereastra cu acest mesaj se închide, metoda
Show cedând controlul.
Metoda Show are mai multe forme în clasa MessageBox, fiind supradefinit . Apelul
acestei func ii se va face în func ie de parametri.
S consider m acum apelul func iei Show cu doi parametri: al doilea parametru se va
referi la textul care apare pe bara de titlu în fereastr de mesaje:
176
S consider m în continuare apelul func iei Show cu trei parametri: al treilea parametru se
va referi la butoanele care pot s apar în fereastra de mesaje (sunt ase variante):
177
II.5.7. Interfa definit de c tre utilizator
Sunt multe aplica ii în care, poate, dorim s ne realiz m o interfa proprie, ca form , în locul
celei dreptunghiulare propus de Visual C#. Dac da, exemplul de mai jos ne va da o idee asupra
a ce trebuie s facem în acest caz.
În primul rând trebuie s ne desen m propria fereastr de viitoare aplica ii. Pentru aceasta
vom folosi, de exemplu, aplica ia Paint.
178
Color m ovalul cu o culoare dorit , iar pentru fundal alegem orice culoare, re inând codul ei
RGB
179
în cazul nostru: Red: 255 Greeen: 255 Blue: 0
S trecem acum la Visual C#. Alegem: File | New Project | Windows Forms Application,
iar ca nume InterfataUtilizator
Aduc controlul PictureBox. Din PictureBox Task aleg imaginea care s apar : oval.jpg
iar la Size Mode aleg StretchImage astfel încât imaginea s fie toat în PictureBox
180
Selectez Form1, iar la propriet ile corespunz toare voi selecta:
Dac vom compila observ m c ob inem, deocamdat , o fereastr în care exist ovalul
desenat de noi, iar fundalul este transparent. Aceast fereastr o putem deplasa, deocamdat
doar folosind proprietatea barei de titlul atunci când inem cursorul mouse-ului ap sat pe ea.
181
Închidem fereastra rezultat i ne continu m proiectul.
Aducem în Fereastra noastr un buton pe care-l vom folosi pentru închiderea ferestrei
rezultat
182
Scriem codul corespunz tor dând dublu clic pe buton:
this.Close();
Includem biblioteca User32.dll în codul nostru: User32.dll este o bibliotec ce con ine rutine
pentru interfa a utilizator (ferestre, meniuri, mesaje etc.)
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr Handle, int
Msg, int Param1, int Param2);
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
}
183
using System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Interfata3
{
public partial class Form1 : Form
{
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr Handle, int Msg,
int Param1, int Param2);
public Form1()
{
InitializeComponent();
}
FormBorderStyle – None
184
Ap s m F5 i surpriz (pl cut ): ob inem ceea ce ne-am propus:
185
II.5.8. Browser creat de c tre utilizator
În Visual C# alegem: File | New Project | Windows Forms Application, iar ca nume
BrowserUtilizator.
webBrowser1.Navigate(textBox1.Text);
Rul m programul i în TextBox vom scrie o adres web. Surpriz pl cut , navigatorul nostru
func ioneaz !
186
Necazurile încep în momentul în care încerc m s maximiz m fereastra browser-ului pentru
a putea vizualiza mai bine informa iile afi ate. Din p cate în acel moment ob inem:
187
Observ m c fereastra WebBrowser-ului nu s-a maximizat odat cu cea a ferestrei aplica iei.
Rezult c aceast încercare de a realiza un browser propriu nu este corect .
188
Deformez cele dou panouri ale containerului astfel încânt panoul de mai sus s fie mai mic,
iar Panoul 2 s ocupe o suprafa mai mare din fereastra noastr .
Singurul lucru care nu ne mul ume te este faptul c la maximizarea ferestrei TextBox-ul i
Button-ul r mân pe loc i nu ader la marginile ferestrei. S corect m acest lucru.
189
Alegem Stânga, Dreapta i Sus dând clic pe segmentele corespunz toare.
Din acest moment cele dou controale aflate în Panoul 1 se vor deplasa odat cu marginile
ferestrei.
Browserul nostru poate fi îmbun t it, în sensul ad ug rii de noi butoane care s ofere
utilizatorului op iuni suplimentare:
Cele patru butoane le putem alinia i aduce la aceea i dimensiune folosind op iunile de pe
bara de instrumente:
Selectarea tuturor butoanelor se poate face fie cu clic i Ctrl pe fiecare, fie înconjurând cu
mouse-ul respectivele butoane (în acest timp butonul stâng al mouse-ului este ap sat).
Pe butoane fiecare poate s pun , dup gustul s u, imagini în loc de aceste simboluri.
190
Vom scrie în continuare codul corespunz tor fiec rui buton, dând dublu clic pe respectivul
control:
webBrowser1.GoBack();
webBrowser1.GoForward();
webBrowser1.GoHome(); //pagina goala
sau
webBrowser1.Navigate("www.google.com");//sau orice alta
//adresa web
control Anchor
textBox Top, Left, Right
button Top, Right
webBrowser Top, Bottom, Left, Right
II.5.9. Ceas
Utilizatorul nu are drept de control asupra tuturor controalelor. Exist controale „de control” al
execut rii (Timer) sau de dialog (OpenFileDialog, SaveFileDialog, ColorDialog, FontDialog,
ContextMenu).
Dintre acestea vom studia în cele ce urmeaz controlul Timer asupra c ruia are drept de
interac iune doar cel care dezvolt aplica ia.
Observ m c aducând din Toolbox controlul Timer, acesta nu se afi eaz pe formular, el
ap rând într-o zon gri a suprafe ei de lucru (Designer).
191
Vom stabili urm toarele propriet i legate de Timer:
193
II.6. Accesarea i prelucrarea datelor prin intermediul SQL Server
II.6.1. Crearea unei baze de date. Conectare i deconectare.
Înainte de a crea orice obiect al unei baze de date trebuie s cre m baza de date. Pentru a
realiza acest lucru trebuie s deschide i aplica ia Microsoft SQL Server Management Studio
Express, i s accepta i conectarea la server-ul local.
În momentul deschiderii aplica iei fereastra acestei aplica ii va con ine fereastra Object Explorer,
fereastra Sumarry i fereastra Properties.
Pentru a crea o nou baz de date din fereastra Object Explorer ce se afl în stânga
ferestrei principale, executa i clic pe butonul din dreapta al mouse-ului dup selectarea folderului
Databases, de unde alege i op iunea New Database..
194
Denumi i aceast baz de date (în exemplul de mai jos noi i-am spus CLASA). Crea i un
tabel alegând în acela i mod ca i cel prezentat mai sus op iunea New Table, din folder-ul Table.
Stabili i cheia primar a tabelei prin selectarea rândului unde dori i s stabili i cheia primar
i apoi prin executarea unui clic pe butonul din dreapta al mouse-ului i alegerea op iunii Set
Primary Key.
195
Pentru a salva tabela creat pân acum executa i clic dreapta pe numele tabelei, alege i
op iunea Save Table i stabili i cu aceast ocazie i numele nou al tabelei.
196
Deconectarea de la baza de date se realizeaz prin alegerea op iunii Disconect Object
Explorer din meniul File al aplica ie, iar în cazul în care aplica ia este deschis i dorim
reconectarea la baza de date alegem din meniul File op iunea Connect Object Explorer.
Anumite instruc iuni cum ar fi Alter sau Create nu sunt accesibile din meniu. Va trebui s
apela i la scrierea lor în cod. Acest lucru poate fi realizat cu ajutorul procedurilor stocate sau cu
ajutorul op iunii SQLCMD.
O procedur stocat este o secven de instruc iuni SQL, salvat in baza de date, care
poate fi apelata de aplica ii diferite. Sql Server compileaz procedurile stocate, ceea ce creste
eficien a utiliz rii lor. De asemenea, procedurile stocate pot avea parametri.
Dac opera iile efectuate pe server sunt mai multe (calcule complexe de ex.) atunci e mai
simplu s apela i la procesarea în Stored Procedures i s returna i doar o list mic de rezultate,
gata procesate. Asta mai ales când procesarea necesit prelucrarea unui volum mare de date.
Pentru a realiza acest lucru va trebui s alege i op iunea New Stored Procedure executând
clic pe butonul din dreapta al mouse-ului pe folderul Stored Procedures din folderul
Programmability al bazei de date pe care o prelucra i.
197
II.6.3.(2) Select
Exemplul 1: am cerut s vizualizez înregistrarile din coloanele ID i NUME ale tabelului Elev
din baza de date CLASA.
198
II.6.3.(3) Insert
Instruc iunea Insert este folosit pentru inserarea noilor rânduri de date în tabele. Ea poate fi
folosit în dou variante:
pentru a crea un singur rând la fiecare rulare, în acest caz valorile pentru rândul de date
respectiv sunt specificate chiar în instruc iune
INSERT INTO nume_tabel
[(lista_de_coloane)]
VALUES (lista_de_valori);
Observa ie:
- lista de coloane este op ional , dar dac este inclus trebuie s fie încadrat între paranteze
- cuvântul cheie NULL poate fi folosit în lista de valori pentru specificarea unei valori nule
pentru o coloan
pentru a insera rânduri multiple într-un tabel se folose te o instruc iune SELECT intern
199
INSERT INTO elev.dbo.CLASA
(ID
,NUME)
SELECT MAX(ID)+1,'POPESCU'
FROM elev.dbo.CLASA
Observa ie:
- lista de coloane este op ional , dar dac este inclus trebuie s fie încadrat între paranteze
- cuvântul cheie NULL poate fi folosit în instruc iunea SELECT pentru specificarea unei valori
nule pentru o coloan
II.6.3.(4) Update
Instruc iunea Update este folosit pentru actualizarea datelor din coloanele unui tabel
Sintaxa ei este urm toarea:
UPDATE [elev].[dbo].[CLASA]
SET [ID] = <ID, numeric,>
,[NUME] = <NUME, nvarchar(50),>
WHERE <Search Conditions,,>
200
Observa ii:
- clauza SET con ine o list cu una sau mai multe coloane, împreun cu o expresie care
specific noua valoare pentru fiecare coloan
- clauza WHERE con ine o expresie care limiteaz rândurile ce vor fi actualizate. Dac o
omitem se vor actualiza toate rândurile tabelului.
II.6.3.(5) DELETE
Instruc iunea DELETE terge unul sau mai multe rânduri dintr-un tabel. În instruc iunea
DELETE nu sunt referite niciodat coloane, deoarece instruc iunea terge rânduri întregi de date,
inclusiv toate valorile datelor din rândurile afectate.
DELETE FROM [elev].[dbo].[CLASA]
WHERE <Search Conditions,,>
Exemplul 5: modifica i numele elevului cu ID-ul 2 din ADAM în POPESCU, pentru a avea
dou înregistr ri cu acela i nume.
UPDATE elev.dbo.CLASA
SET
NUME = 'POPESCU'
WHERE ID=2
Folosi i acum instruc iunea DELETE astfel:
DELETE FROM elev.dbo.CLASA
WHERE NUME='POPESCU'
Observa ii:
- clauza WHERE este op ional , dar ATEN IE dac ve i renun a la ea se vor terge toate
înregistr rile existente
- atunci când include i clauza WHERE ea specific rândurile care urmeaz a fi terse. Va fi
tears orice înregistrare pentru care condi ia indicat este adev rat .
MODIFY – ne permite modificarea numelui unei coloane, modificarea tipului de date al unui
rând, sau modificarea cheii primare.
201
ALTER
Dup ce a i creat un tabel, aproape tot ceea ce a i specificat în instruc iunea CREATE
TABLE poate fi modificat folosind instruc iunea ALTER TABLE. Cu ajutorul ei se pot specifica toate
restric iile necesare(cheie primar , cheie extern , unicitate, verificare, etc).
ALTER TABLE <nume tabela> ADD|DROP|MODIFY (specifica ii privind coloana modificata sau nou creata);
CREATE
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] nume_tabela
Nume_camp tip_camp [NOT NULL | NULL] [DEFAULT default_value] AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
Pentru fiecare câmp se stabile te numele i tipul acestuia, putând nominaliza o serie de
parametri facultativi (sunt acceptate sau nu valorile nule, setarea valorii implicite, câmpul sa fie
autoincrementat sau sa fie creat drept cheie primar ).
Exemplul 7:
202
Pentru a executa aceasta comanda faceti clic pe butonul
Pentru a vizualiza efectul acestei comenzi folosi i comanda Select ca in exemplul de mai
Dup cum observa i se pot vizualiza câmpurile definite în tabela Flori. Pentru a popula
aceasta tabel trebuie s o deschide i cu Open.
FUNC IA COUNT – returneaz num rul de câmpuri dintr-o tabel care corespund interog rii.
Sintaxa instruc iunii este:
SELECT COUNT (nume coloana)
FROM nume tabel
WHERE <Search Conditions,,>
Exemplul 8: pentru tabela Salarii am cerut câte persoane au salariu mai mare decât 1200.
203
Func ia SUM – returneaz suma total dintr-o coloan a c rei tip de date a fost declarat
ini ial numeric.
SELECT SUM(column_name) FROM table_name
Exemplul 9: pentru tabela Salarii cerem suma tuturor salariilor înregistrate pe coloana
Salar.
Exemplul 10: cerem s se afi eze cel mai mare salariu din tabela Salarii.
Exemplul 11: cerem s se afi eze cel mai mare salariu din tabela Salarii.
204
Ordonarea datelor dintr-o tabel – se poate realiza cu ajutorul instruc iunii Order By
Sintaxa:
SELECT column_name(s)
FROM table_name
ORDER BY column_name(s) ASC|DESC
Exemplul 12: am cerut s se ordoneze alfabetic datele înregistrate pe coloana Nume din
tabela Salarii.
205
Alege i sursa de date pentru acest proiect executând clic pe butonul AddProject Data
Source din fereastra DataGridView Task, alege i imediat dup aceasta sursa de date i baza de
date urm rind exemplele de mai jos.
Înainte de a finaliza prin executarea unui clic pe butonul Ok din fereastra Add Connection,
nu uita i s verifica i conexiunea executând clic pe butonul Test Connection.
Conexiunea la baza de date se finalizeaz prin alegerea obiectului pe care dori i s îl utiliza i
în formularul creat.
206
Dup finalizarea conexiunii sursa generat o pute i vizualiza în Form1.cs. Pentru exemplul
nostru am ales o baz de date numit SALARII, tabela utilizat fiind SALAR_ANGAJAT.
Exemplul 1:
namespace WindowsFormsApplication1
{ public partial class Form1 : Form
{ public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.sALAR_ANGAJATTableAdapter.Fill(this.sALARIIDataSet.SALAR_ANGAJAT
);
}}}
Rula i aplica ia alegând op iunea Start Debugging din meniul Debug i ve i ob ine afi area
datelor într-un formular ca în exemplul de mai jos.
Afi area înregistr rilor din tabel se poate ob ine i prin alegerea op iunii Preview din
fereastra DataGridView Task i executând clic pe butonul Preview din fereastra care se deschide
Preview Data .
Cheia primar se poate stabili din fereastra SalariiDataset executând clic pe butonul
din dreapta al mouse-ului i alegând op iunea Set Primary Key pentru câmpul respectiv.
207
Stabili i cheia primar a tabelei prin selectarea rândului unde dori i s stabili i cheia primar
i apoi prin executarea unui clic pe butonul din dreapta al mouse-ului i alegerea op iunii Set
Primary Key.
Dup cum observa i op iunile prezente în acest meniu v mai pot ajuta s terge i o coloan
în tabel, s insera i o coloan din tabel s stabili i sau s modifica i propriet ile unei coloane deja
definite sau s vizualiza i codul generat.
Atunci când într-un formular utiliz m un tabel trebuie s avem posibilitatea de a utiliza
func iile ce opereaz asupra datelor incluse în el. Toate instruc iunile prezentate în capitolul
Introducere în limbajul SQL pot fi accesate i pe un formular. Prin "tragerea" unor obiecte din
fereastra Data Sources în fereastra noastr nou , se creeaz automat obiecte specifice. În partea
de jos a figurii se pot observa obiectele de tip Dataset, TableAdapter, BindingSource,
BindingNavigator i, în fereastr , TableGridView.
BindingNavigator este un tip ce permite, prin instan iere, construirea barei de navigare care
faciliteaz opera ii de deplasare, editare, tergere i ad ugare în tabel.
Se observ c reprezentarea vizual a fiec rui obiect este înzestrat cu o s get în partea
de sus, în dreapta. Un clic pe aceast s geat activeaz un meniu contextual cu lista principalelor
opera ii ce se pot efectua cu obiectul respectiv.
Meniul contextual asociat grilei în care vor fi vizualizate datele permite configurarea modului
de lucru cu grila (sursa de date, opera iile permise i altele).
208
Prezent m un exemplu pentru inserarea unor noi date în tabelul Salar_Angajat:
alega i op iunea Add Query din SALAR_ANGATTableAdapter Tasks
introduce i instruc iunea INSERT în forma dorit , executa i clic pe butonul Query Builder pentru
a vizualiza efectul, si clic pe butonul Execute Query pentru a o lansa în execu ie
pentru a vizualiza efectul acestei instruc iuni pute i lansa în execu ie aplica ia
În acela i mod se pot utiliza celelalte instruc iuni i func ii ale limbajului SQL.
209
De obicei, sursa de date este o baz de date, dar ar putea de asemenea s fie un fi ier
text, o foaie Excel, un fi ier Access sau un fi ier XML.
In aplica iile tradi ionale cu baze de date, clien ii stabilesc o conexiune cu baza de date i
men in aceast conexiune deschis pân la încheierea execut rii aplica iei.
Conexiunile deschise necesit alocarea de resurse sistem. Atunci când men inem mai
multe conexiuni deschise server-ul de baze de date va r spunde mai lent la comenzile clien ilor
întrucât cele mai multe baze de date permit un num r foarte mic de conexiuni concurente.
ADO.NET permite i lucrul în stil conectat dar i lucrul în stil deconectat, aplica iile
conectându-se la server-ul de baze de date numai pentru extragerea i actualizarea datelor. Acest
lucru permite reducerea num rului de conexiuni deschise simultan la sursele de date.
ADO.NET ofer instrumentele de utilizare i reprezentare XML pentru transferul datelor
între aplica ii i surse de date, furnizând o reprezentare comun a datelor, ceea ce permite
accesarea datelor din diferite surse de diferite tipuri i prelucrarea lor ca entit i, f r s fie necesar
s convertim explicit datele în format XML sau invers.
Aceste caracteristici sunt determinate în stabilirea beneficiilor furnizate de ADO.NET:
Interoperabilitate. ADO.NET poate interac iona u or cu orice component care suport XML.
Durabilitate. ADO.NET permite dezvoltarea arhitecturii unei aplica ii datorit modului de
transfer a datelor între nivelele arhitecturale.
Programabilitate. ADO.NET simplific programarea pentru diferite task-uri cum ar fi comenzile
SQL, ceea ce duce la o cre tere a productivit ii i la o sc dere a num rului de erori.
Performan . Nu mai este necesar conversia explicit a datelor la transferul între aplica ii, fapt
care duce la cre te performan elor acestora.
Accesibilitate. Utilizarea arhitecturii deconectate permite accesul simultan la acela i set de
date. Reducerea num rului de conexiuni deschise simultan determin utilizarea optim a
resurselor.
210
II.8.2. Furnizori de date (Data Providers)
Din cauza existen ei mai multor tipuri de surse de date este necesar ca pentru fiecare tip de
protocol de comunicare s se foloseasc o bibliotec specializat de clase.
.NET Framework include SQL Server.NET Data Provider pentru interac iune cu
Microsoft SQL Server, Oracle Data Provider pentru bazele de date Oracle i OLE DB Data
Provider pentru accesarea bazelor de date ce utilizeaz tehnologia OLE DB pentru expunerea
datelor (de exemplu Access, Excel sau SQL Server versiune mai veche decât 7.0).
Furnizorul de date permite unei aplica ii s se conecteze la sursa de date, execut comenzi
i salveaz rezultate. Fiecare furnizor de date cuprinde componentele Connection, Command,
DataReader i DataAdapter.
II.8.3. Conectare
Înainte de orice opera ie cu o surs de date extern , trebuie realizat o conexiune (leg tur )
cu acea surs . Clasele din categoria Connection (SQLConnection, OleDbConnection etc.) con in
date referitoare la sursa de date (loca ia, numele i parola contului de acces, etc.), metode pentru
deschiderea/închiderea conexiunii, pornirea unei tranzac ii etc. Aceste clase se g sesc în subspa ii
(SqlClient, OleDb etc.) ale spa iului System.Data. În plus, ele implementeaz interfa a
IdbConnection.
Pentru deschiderea unei conexiuni prin program se poate instan ia un obiect de tip conexiune,
precizându-i ca parametru un ir de caractere con inând date despre conexiune.
Toate exemplele pe care le vom prezenta în continuare vor avea la baz o tabel cu
urm toarea structur :
211
SqlConnection co = new SqlConnection(".\\SQLEXPRESS;Initial
Catalog=SALARII;IntegratedSecurity=SSPI");
ConnectionTimeout (int, cu accesor de tip get): specific num rul de secunde pentru care un
obiect de conexiune poate s a tepte pentru realizarea conect rii la server înainte de a se genera
o excep ie. (implicit 15). Se poate specifica o valoare diferit de 15 în ConnectionString folosind
parametrul Connect Timeout, Valoarea Timeout=0 specific a teptare nelimitat .
Exemplul 3:
unde:
Database (string, read-only): returneaz numele bazei de date la care s–a f cut conectarea.
Este necesar pentru a ar ta unui utilizator care este baza de date pe care se face operarea
Provider (de tip string, read-only): returneaz furnizorul de date
ServerVersion (string, read-only): returneaz versiunea de server la care s–a f cut conectarea.
State (enumerare de componente ConnectionState, read-only): returneaz starea curent a
conexiunii. Valorile posibile: Broken, Closed, Connecting, Executing, Fetching, Open.
II.8.3.(1) Metode
Open(): deschide o conexiune la baza de date
Close() i Dispose(): închid conexiunea i elibereaz toate resursele alocate pentru ea
BeginTransaction(): pentru executarea unei tranzac ii pe baza de date; la sfâr it se apeleaz
Commit() sau Rollback().
212
ChangeDatabase(): se modific baza de date la care se vor face conexiunile. Noua baz de
date trebuie s existe pe acela i server ca i precedenta.
CreateCommand(): creeaz o comand (un obiect de tip Command) valid asociat conexiunii
curente.
II.8.3.(2) Evenimente
StateChange: apare atunci când se schimb starea conexiunii. Handlerul corespunz tor (de tipul
delegat StateChangeEventHandler) spune între ce st ri s-a f cut tranzi ia.
InfoMessage: apare când furnizorul trimite un avertisment sau un mesaj c tre client.
II.8.4. Comenzi
Clasele din categoria Command (SQLCommand, OleDbCommand etc.) con in date
referitoare la o comand SQL (SELECT, INSERT, DELETE, UPDATE) i metode pentru
executarea unei comenzi sau a unor proceduri stocate. Aceste clase implementeaz interfa a
IDbCommand. Ca urmare a interog rii unei baze de date se ob in obiecte din categoriile
DataReader sau DataSet. O comand se poate executa numai dup ce s-a stabilit o conxiune cu
baza de date corespunz toare.
Obiectele de tip SQLCommand pot fi utilizate într-un scenariu ce presupune deconectarea
de la sursa de date dar i în opera ii elementare care presupun ob inerea unor rezultate imediate.
Vom exemplifica utilizarea obiectelor de tip Command în opera ii ce corespund acestui caz.
II.8.4.(1) Propriet i
CommandText (String): con ine comanda SQL sau numele procedurii stocate care se execut
pe sursa de date.
CommandTimeout (int): reprezint num rul de secunde care trebuie s fie a teptat pentru
executarea comenzii. Dac se dep este acest timp, atunci se genereaz o excep ie.
CommandType (enumerare de componente de tip CommandType): reprezint tipul de
comand care se execut pe sursa de date. Valorile pot fi: StoredProcedure (apel de procedur
stocat ), Text (comand SQL obi nuit ), TableDirect (numai pentru OleDb)
Connection (System. Data. [Provider].PrefixConnection): con ine obiectul de tip conexiune
folosit pentru legarea la sursa de date.
Parameters (System.Data.[Provider].PrefixParameterCollection): returneaz o colec ie de
parametri care s-au transmis comenzii.
Transaction (System.Data.[Provider].PrefixTransaction): permite accesul la obiectul de tip
tranzac ie care se cere a fi executat pe sursa de date.
II.8.5. DataReader
213
Datele pot fi explorate în mod conectat (cu ajutorul unor obiecte din categoria DataReader),
sau pot fi preluate de la surs (dintr-un obiect din categoria DataAdapter) i înglobate în aplica ia
curent (sub forma unui obiect din categoria DataSet).
Clasele DataReader permit parcurgerea într-un singur sens a sursei de date, f r
posibilitate de modificare a datelor la surs . Dac se dore te modificarea datelor la surs , se va
utiliza ansamblul DataAdapter + DataSet. Datorit faptului c cite te doar înainte (forward-only)
permite acestui tip de date s fie foarte rapid în citire. Overhead-ul asociat este foarte mic
(overhead generat cu inspectarea rezultatului i a scrierii în baza de date).
Dac într-o aplica ie este nevoie doar de informa ii care vor fi citite o singura dat , sau
rezultatul unei interog ri este prea mare ca sa fie re inut în memorie (caching) DataReader este
solu ia cea mai bun .
Un obiect DataReader nu are constructor, ci se ob ine cu ajutorul unui obiect de tip
Command i prin apelul metodei ExecuteReader() (vezi exerci iile de la capitolul anterior). Evident,
pe toat durata lucrului cu un obiect de tip DataReader, conexiunea trebuie s fie activ . Toate
clasele DataReader (SqlDataReader, OleDbDataReader etc.) implementeaz interfa a
IDataReader.
II.8.5.(1) Propriet i:
IsClosed (boolean, read-only)- returnez true dac obiectul este deschis i fals altfel
HasRows (boolean,read-only)- verific dac reader-ul con ine cel pu in o înregistrare
Item (indexator de câmpuri)
FieldCount-returneaz num rul de câmpuri din înregistrarea curent
II.8.5.(2) Metode:
Close() închidere obiectului i eliberarea resurselor; trebuie s precead închiderea conexiunii.
GetBoolean(), GetByte(), GetChar(), GetDateTime(), GetDecimal(), GetDouble(), GetFloat(),
GetInt16(), GetInt32(), GetInt64(), GetValue(), GetString() returneaz valoarea unui câmp
specificat, din înregistrarea curent
GetBytes(), GetChars() citirea unor octe i/caractere dintr-un câmp de date binar
GetDataTypeName(), GetName() returneaz tipul/numele câmpului specificat
IsDBNull() returneaz true dac în câmpul specificat prin index este o valoare NULL
NextResult()determin trecerea la urm torul rezultat stocat în obiect (vezi exemplul)
Read() determin trecerea la urm toarea înregistrare, returnând false numai dac aceasta nu
exist ; de re inut c ini ial pozi ia curent este înaintea primei înregistr ri.
DataReader ob ine datele într-un stream secven ial. Pentru a citi aceste informa ii trebuie
apelat metoda Read; aceasta cite te un singur rând din tabelul rezultat. Metoda clasic de a citi
informa ia dintr-un DataReader este de a itera intr-o bucla while.
214
II.8.6. Constructori i metode asociate obiectelor de tip comand
SqlCommand()
215
Exemplul 6: Am construit o nou tabel tot în baza de date salarii numit telefoane. Con inutul
ei este prezentat mai jos.
216
- SequentialAccess (pentru manevrarea valorilor binare cu GetChars() sau GetBytes()),
- SingleResult (se returneaz un singur set de rezultate),
- SingleRow (se returneaz o singur linie).
DataReader implementeaz i indexatori. Nu este foarte clar pentru cineva care cite te codul
care sunt coloanele afi ate decât dac s-a uitat i în baza de date. Din aceasta cauz este
preferat utilizarea indexatorilor de tipul string. Valoarea indexului trebuie s fie numele coloanei
din tabelul rezultat. Indiferent c se folose te un index numeric sau unul de tipul string indexatorii
întorc totdeauna un obiect de tipul object fiind necesar conversia.
Exemplul 7: cele dou surse scrise mai jos sunt echivalente. Ele afi eaz datele înregistrate
pe coloana NUME.
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr[1]); }
rdr.Close();
Console.ReadLine();
sau
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr["nume"]); }
rdr.Close();
Console.ReadLine();
Exemplul 8:
217
Int32 var = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM SALAR_ANGAJAT",co);
var=(Int32) cmd.ExecuteScalar();
Console.WriteLine(var);
Console.ReadLine();
Pentru extragerea datelor cu ajutorul unui obiect SqlCommand trebuie s utiliz m metoda
ExecuteReader care returneaz un obiect SqlDataReader.
218
Exemplul 9: vom insera în tabela salar_angajat o nou înregistrare i vom afi a tot con inutul
tabelei
Exemplul 10: vom modifica numele unui angajat, din BARBU în BIBIRE în tabela
SALAR_ANGAJAT i vom afi a tot con inutul tabelei
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
string updateString = @"update SALAR_ANGAJAT set NUME = 'BIBIRE' where
NUME = 'BARBU'";
SqlCommand cmd = new SqlCommand(updateString);
cmd.Connection = co; // Stabilim conexiunea
cmd.ExecuteNonQuery();//Apel m ExecuteNonQuery pentru executarea comenzii
SqlCommand comand = new SqlCommand("SELECT * FROM SALAR_ANGAJAT", co);
SqlDataReader reader = comand.ExecuteReader();
while (reader.Read()) Console.WriteLine(String.Format("\t{0}\t{1}\t{2}
\t {3} \t {4}",reader[0], reader[1], reader[2], reader[3], reader[4]));
Console.ReadLine();reader.Close(); }
219
II.8.10. tergerea datelor
Se utilizeaz aceea i metod ExecuteNonQuery.
Exemplul 11: vom terge înregistrarea cu numele BIBIRE din tabela SALAR_ANGAJAT i
vom afi a tot con inutul tabelei
Exemplul 12: Realiza i o conexiune la baza de date SALAR_ANGAJAT i afi a i cea mai
mare vechime i suma tuturor salariilor înregistrate.
Int32 var = 0; Int32 suma = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand comand1 = new SqlCommand("select MAX(VECHIME) FROM
SALAR_ANGAJAT",co);
var = (Int32)comand1.ExecuteScalar();
Console.Write(" CEA MAI MARE VECHIME A UNUI ANGAJAT ESTE DE :");
Console.Write(var); Console.WriteLine(" ANI");
SqlCommand comand2 = new SqlCommand("select SUM(SALAR) FROM
SALAR_ANGAJAT", co);
suma = (Int32)comand2.ExecuteScalar();
Console.Write(" SUMA SALARIILOR TUTUROR ANGAJATILOE ESTE: ");
Console.Write(suma); Console.WriteLine(" RON");
Console.ReadLine();
220
Exemplul 12: Realiza i func ii care s implementeze opera iile elementare asupra unei
baze de date i verifica i func ionalitatea lor.
conexiunea la baza de date
class program
{
SqlConnection conn;
public program()
{
conn = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");}
apelarea din func ia main a func iilor care vor realiza afi area datelor, inserarea unei noi
valori, tergerea unor valori, actualizare
static void Main()
{
program scd = new program();
Console.WriteLine("SALARII ANGAJATI");
scd.ReadData();
scd.Insertdata();
Console.WriteLine("AFISARE DUPA INSERT");
scd.ReadData(); scd.UpdateData();
Console.WriteLine("AFISARE DUPA UPDATE");
scd.ReadData(); scd.DeleteData();
Console.WriteLine("AFISARE DUPA DELETE");
scd.ReadData();
int number_inregistrari = scd.GetNumberOfRecords();
Console.WriteLine("Numarul de inregistrari: {0}",
number_inregistrari);
Console.ReadLine();
}
func ia de citire i afi are a datelor
public void ReadData()
{
SqlDataReader rdr = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("select * from
salar_angajat", conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
Console.WriteLine(String.Format("\t{0}\t{1}\t{2} \t {3} \t {4}",
rdr[0], rdr[1], rdr[2], rdr[3], rdr[4]));
}
finally
{
if (rdr != null) { rdr.Close(); }
if (conn != null) { conn.Close(); }
}
}
func ia care realizeaz inserarea unei noi valori
221
public void Insertdata()
{ try
{conn.Open();
string insertString = @"insert into salar_angajat(ID ,NUME
,PRENUME ,VECHIME ,SALAR)values (6,'BARBU','EUGENIU',17,1993)";
SqlCommand cmd = new SqlCommand(insertString, conn);
cmd.ExecuteNonQuery();}
finally
{ if (conn != null) { conn.Close(); } }}
222
II.8.11. DataAdapter i DataSet
Folosirea combinat a obiectelor DataAdapter i DataSet permite opera ii de selectare,
tergere, modificare i ad ugare la baza de date. Clasele DataAdapter genereaz obiecte care
func ioneaz ca o interfa între sursa de date i obiectele DataSet interne aplica iei, permi ând
prelucr ri pe baza de date. Ele gestioneaz automat conexiunea cu baza de date astfel încât
conexiunea s se fac numai atunci când este imperios necesar.
Un obiect DataSet este de fapt un set de tabele rela ionate. Folose te serviciile unui obiect
DataAdapter pentru a- i procura datele i trimite modific rile înapoi c tre baza de date. Datele sunt
stocate de un DataSet în format XML, acela i folosit i pentru transferul datelor.
În exemplul urm tor se preiau datele din tablele salar_angajat i telefoane:
SqlDataAdapter de=new SqlDataAdapter("SELECT nume,prenume FROM salar_angajat”, conn);
de.Fill(ds," salar_angajat ");//transfer datele în datasetul ds sub forma unei
tabele locale numite salariu_angajat
SqlDataAdapter dp=new SqlDataAdapter("SELECT nume,telefon FROM telefoane”,conn);
dp.Fill(ds," telefoane ");//transfer datele în datasetul ds sub forma unei tabele
locale numite telefoane
Propriet i
DeleteCommand, InsertCommand, SelectCommand, UpdateCommand (Command), con in
comenzile ce se execut pentru selectarea sau modificarea datelor în sursa de date.
MissingSchemaAction (enumerare) determin ce se face atunci când datele aduse nu se
potrivesc peste schema tablei în care sunt depuse. Poate avea urm toarele valori:
223
Error - se genereaz o excep ie de tipul InvalidOperationException.
Metode
Constructori:SqlDataAdapter()|SqlDataAdapter(obiect_comanda)|
SqlDataAdapter(string_comanda, conexiune);
Fill() permite umplerea unei tabele dintr-un obiect DataSet cu date. Permite specificarea
obiectului DataSet în care se depun datele, eventual a numelui tablei din acest DataSet, num rul
de înregistrare cu care s se înceap popularea (prima având indicele 0) i num rul de înregistr ri
care urmeaz a fi aduse.
Update() permite transmiterea modific rilor efectuate într-un DataSet c tre baza de date.
Un DataSet este format din Tables (colec ie format din obiecte de tip DataTable;
DataTable este compus la rândul lui dintr-o colec ie de DataRow i DataColumn), Relations
(colec ie de obiecte de tip DataRelation pentru memorarea leg turilor p rinte–copil) i
ExtendedProperties ce con ine propriet i definite de utilizator.
Scenariul uzual de lucru cu datele dintr-o tabel con ine urm toarele etape:
popularea succesiv a unui DataSet prin intermediul unuia sau mai multor obiecte DataAdapter,
apelând metoda Fill
procesarea datelor din DataSet folosind numele tabelelor stabilite la umplere,
ds.Tables["salar_angajat"], sau indexarea acestora, ds.Tables[0], ds.Tables[1]
actualizarea datelor prin obiecte comand corespunz toare opera iilor INSERT, UPDATE i
DELETE. Un obiect CommandBuilder poate construi automat o combina ie de comenzi ce reflect
modific rile efectuate.
A adar, DataAdapter deschide o conexiune doar atunci când este nevoie i o închide
imediat aceasta nu mai este necesar .
De exemplu DataAdapter realizeaz urm toarele opera iuni atunci când trebuie sa populeze
un DataSet:deschide conexiunea, populeaz DataSet-ul,închide conexiunea i urm toarele
opera iuni atunci când trebuie sa fac update pe baza de date: deschide conexiunea, scrie
modific rile din DataSet în baza de date, închide conexiunea. Între opera iunea de populare a
DataSet-ului i cea de update conexiunile sunt închise. Intre aceste opera ii în DataSet se poate
scrie sau citi.
Crearea unui obiect de tipul DataSet se face folosind operatorul new.
DataSet dsProduse = new DataSet ();
Constructorul unui DataSet nu necesit parametri. Exist totu i o supraînc rcare a
acestuia care prime te ca parametru un string i este folosit atunci când trebuie s se fac o
serializare a datelor într-un fi ier XML. În exemplul anterior avem un DataSet gol i avem nevoie
de un DataAdapter pentru a-l popula.
Un obiect DataAdapter con ine mai multe obiecte Command (pentru inserare, update,
delete i select) i un obiect Connection pentru a citi i scrie date.
224
În exemplul urm tor construim un obiect de tipul DataAdapter, daSALAR. Comanda SQL
specific cu ce date va fi populat un DataSet, iar conexiunea co trebuie s fi fost creat anterior,
dar nu i deschis . DataAdapter-ul va deschide conexiunea la apelul metodelor Fill i Update.
SqlDataAdapter daSALAR =
new SqlDataAdapter ("SELECT NUME, SALAR SALARIU_ANGAJAT", co);
Prin intermediul constructorului putem instan ia doar comanda de interogare. Instan ierea
celorlalte se face fie prin intermediul propriet ilor pe care le expune DataAdapter, fie folosind
obiecte de tipul CommandBuilder.
În exemplul urm tor va fi populat DataSet-ul dsNUME. Cel de-al doilea parametru (string)
reprezint numele tabelului (nu numele tabelului din baza de date, ci al tabelului rezultat în
DataSet) care va fi creat. Scopul acestui nume este identificarea ulterioar a tabelului. În cazul în
care nu sunt specificate numele tabelelor, acestea vor fi ad ugate în DataSet sub numele Table1,
Table2, ...
Un DataSet poate fi folosit ca surs de date pentru un DataGrid din Windows Forms sau
ASP.Net .
Dup ce au fost f cute modific ri într-un DataSet acestea trebuie scrise i în baza de date.
Actualizarea se face prin apelul metodei Update.
225
II.9. Aplica ie final
Pentru a realiza aceast aplica ie trebuie s crea i o baz de date (noi am numit-o
salarii) baz în care trebuie s crea i o tabel (noi am anumit-o salar_angajat) cu cinci câmpuri (ID,
NUME, PRENUME, VECHIME, SALAR) pe care o pute i popula cu câteva înregistr ri.
Din meniul File al aplica iei Microsoft Visual C# 2008 Express Edition alege i New
Project/Windows Forms Application. Pe formular va trebui s „trage i” un buton (INSERARE), cinci
etichete(ID, NUME, PRENUME, VECHIME, SALAR), cinci casete de text pozi ionate sub fiecare
etichet , o etichet în care s introduce i textul „NUM R DE MODIFIC RI”, iar în dreptul ei o
caset de text. Urm ri i imaginea din figura de mai jos:
În sursa din spatele formularului declara i o variabil de tip int nrmodificari care va contoriza
permanent num rul de modific ri aduse tabelei ( tergeri, inser ri) i conexiunea la baza de date.
Pentru a vizualiza i con inutul tabelei pe formular va trebui s mai „trage i” un buton
„AFISARE” , patru etichete (pentru nume,prenume,vechime i salar), iar în sursa butonului
„AFISARE” s completa i codul de mai jos, cod care v va permite afi area celor patru câmpuri
din tabel .
227
private void button2_Click(object sender, EventArgs e)
{
string selectSQL = "SELECT * FROM salar_angajat";
SqlCommand cmd = new SqlCommand(selectSQL, co);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "salar_angajat");
label7.Text = "NUME"; label8.Text = "PRENUME"; label9.Text = "VECHIME"; label10.Text =
"SALAR";
foreach (DataRow r in ds.Tables["salar_angajat"].Rows)
{
label7.Text = label7.Text +"\n" + r["nume"] + "\n";
label8.Text = label8.Text + "\n"+r["prenume"] + "\n";
label9.Text = label9.Text +"\n"+ r["vechime"] + "\n";
label10.Text = label10.Text + "\n"+r["salar"] + "\n";
}
}
V întoarce i acum pe formular în mod design, i mai ad uga i un buton pe care noi l-
am numit „STERGERE”, o etichet în care va trebui s introduce i textul „INTRODUCETI NUMELE
ANGAJATULUI CE TREBUIE STERS” i o caset de text, pe care o ve i pozi iona în dreptul
etichetei.
228
caset de text i s completa i sursa butonului cu codul care v va permite ob inerea sumei
salariilor înregistrate în tabel apelând func ia SUM.
private void button4_Click(object sender, EventArgs e)
{
int suma;
SqlCommand cmd = new SqlCommand("select SUM(SALAR) FROM SALAR_ANGAJAT", co);
suma= (int)cmd.ExecuteScalar();
textBox8.Text = Convert.ToString(suma);
}
În acest moment preg ti i suprafa a formularului pentru includerea unor noi butoane,
casete de text i etichete, prin :
modificarea pozi iilor celor deja existente
ad ugarea a patru etichete pe care vor fi introduse textele NUME, PRENUME, VECHIME,
SALAR
229
Ad uga i dou butoane i dou casete de text pe care încerca i s le pozi iona i sub
butonul SUMA SALARII. Textul celor dou butoane va fi: Cea mai mica vechime, respectiv Cel mai
mare salariu.
Sursele din spatele celor dou butoane vor fi cele din exemplele de mai jos:
230
label9.Text = label9.Text + "\n" + r["vechime"] + "\n";
label10.Text = label10.Text + "\n" + r["salar"] + "\n";
}
}
În acest moment pute i spune c a i creat o aplica ie care v ajut s gestiona i într-o
oarecare m sur o tabel a unei baze de date. Toate func iile i comenzile SQL prezentate în
acest capitol se pot reg si într-o aplica ie de acest gen. Totul este s v stabili i priorit ile înainte
de a v apuca de lucru, iar dac pe parcurs mai dori i s ad uga i sau s modifica i aplica ia a i
observat c acest lucru este posibil.
231