Sunteți pe pagina 1din 232

m

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

I.1. Introducere in .NET

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

I.1.1. Arhitectura .NET Framework

Servicii WEB Formulare

Data and XML classes


(ADO.NET, SQL, XML etc.)

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)

I.1.2. Compilarea programelor

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

I.1.3. De ce am alege .NET?

Î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. Introducere în limbajul C#

I.2.1. Caracterizare

Limbajul C# a fost dezvoltat de o echip restrâns de ingineri de la Microsoft, echip din


care s-a eviden iat Anders Hejlsberg (autorul limbajului Turbo Pascal i membru al echipei care a
proiectat Borland Delphi).
C# este un limbaj simplu, cu circa 80 de cuvinte cheie i 12 tipuri de date predefinite. El
permite programarea structurat , modular i orientat obiectual, conform perceptelor moderne ale
program rii profesioniste.
Principiile de baz ale program rii orientate pe obiecte (ÎNCAPSULARE, MO TENIRE,
POLIMORFISM) sunt elemente fundamentale ale program rii C#. În mare, limbajul mo tene te
sintaxa i principiile de programare din C++. Sunt o serie de tipuri noi de date sau func iuni diferite
ale datelor din C++, iar în spiritul realiz rii unor secven e de cod sigure (safe), unele func iuni au
fost ad ugate (de exemplu, interfe e i deleg ri), diversificate (tipul struct), modificate (tipul string)
sau chiar eliminate (mo tenirea multipl i pointerii c tre func ii). Unele func iuni (cum ar fi accesul

5
direct la memorie folosind pointeri) au fost p strate, dar secven ele de cod corespunz toare se
consider „nesigure”.

I.2.2. Crearea aplica iilor consol

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)
{
}
}
}

Completa i func ia Main cu urm toarea linie de program:

Console.WriteLine("Primul program");

Ve i observa c în scrierea programului sunte i asista i de IntelliSense, ajutorul contextual.

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)

rapid cu asisten de depanare (Start Debugging F5 sau cu butonul din bara de


instrumente)
rulare pas cu pas (Step Into F11 i Step Over F10)
rulare rapid pân la linia marcat ca punct de întrerupere (Toggle Breakpoint F9 pe
linia respectiv i apoi Start Debugging F6). Încetarea urm ririi pas cu pas (Stop
Debugging Shift+F5) permite ie irea din modul depanare i revenirea la modul normal
de lucru. Toate op iunile i rulare i depanare se g sesc în meniul Debug al mediului de
programare.

7
Icoanele din IntelliSense i semnifica ia lor

I.2.3. Structura unui program C#

Majoritatea c r ilor care trateaz limbaje de programare încep cu un exemplu, devenit


celebru, ap rut pentru prima dat în edi ia din 1978 a c r ii „The C Programming Language” a lui
Brian W. Kernighan i Dennis M. Ritchie, „p rin ii” limbajului C. Vom prezenta i noi acest exemplu
adaptat la limbajul C#:

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.

S coment m programul de mai sus:


linia 1: este o directiv care specific faptul c se vor folosi clase incluse în spa iul de nume
System. În cazul nostru, se va folosi clasa Console.
linia 3: spa iul nostru de nume
linia 5: orice program C# este alc tuit din una sau mai multe clase
linia 7: metoda Main, „punctul de intrare” în program
linia 9: clasa Console, amintit mai sus, este folosit pentru opera iile de intrare/ie ire.
Aici se apeleaz metoda WriteLine din aceast clas , pentru afi area
mesajului dorit pe ecran.

În C#, simplificat vorbind, un program poate namespace

fi privit ca având mai multe „straturi”: avem cod în class


interiorul metodelor, care, la rândul lor, se afl în
metod
interiorul claselor, aflate în interiorul
namespaces-urilor.
cod

Conven ie: S-a adoptat urm toarea


conven ie de scriere: în cazul în care folosim nume
compuse din mai multe cuvinte, fiecare cuvânt
este scris cu majuscul : HelloWorld,
WriteLine. Aceast conven ie poart numele de
Conven ie Pascal. Asem n toare este Conven ia c mil , cu diferen a c primul caracter din
primul cuvânt este liter mic .

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

Limbajul C# admite trei tipuri de comentarii:


comentariu pe un rând prin folosirea //. Tot ce urmeaz dup caracterele // sunt
considerate, din acel loc pân la sfâr itul rândului, drept comentarii.

// Acesta este un comentariu pe un singur rand

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

creare document în format XML folosind ///. Nepropunându-ne s intr m în


am nunte, amintim c XML (eXtensible Markup Language) a fost proiectat în scopul
transferului de date între aplica ii pe Internet, fiind un model de stocare a datelor
nestructurate i semi-structurate.

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

Conven ii pentru nume:


în cazul numelor claselor, metodelor, a propriet ilor, enumer rilor, interfe elor, spa iilor
de nume, fiecare cuvânt care compune numele începe cu majuscul ;
în cazul numelor variabilelor, dac numele este compus din mai multe cuvinte, primul
începe cu minuscul , celelalte cu majuscul .

I.2.4.2. Cuvinte cheie în C#

Cuvintele cheie sunt identificatori predefini i cu semnifica ie special pentru compilator.


Definim în C# urm toarele cuvinte cheie:

abstract as base bool break


byte case catch char checked
class const continue decimal default
delegate do double else enum
event explicit extern false finally
fixed float for foreach goto
if implicit in int interface
internal is lock long namespace
new null object operator out
override params private protected public
readonly ref return sbyte sealed
short sizeof stackalloc static string
struct switch this throw true
try typeof uint ulong unchecked
unsafe ushort using virtual void
volatile while

Pentru a da semnifica ii specifice codului, în C# avem i cuvinte cheie contextuale:

ascending by descending equals from


get group into join let
on orderby partial select set
value where yield

În general, cuvintele cheie nu pot fi folosite în programele pe care le scriem, dându-le o


alt semnifica ie. În cazul în care, totu i, dorim s le d m o alt semnifica ie, va trebui s le scriem
cu simbolul „@” ca prefix. Datorit neclarit ilor care pot s apar , se va evita folosirea cuvintelor
rezervate în alte scopuri.

11
I.2.4.3. Constante

În C# exist dou modalit i de declarare a constantelor: folosind const sau folosind


modificatorul readonly. Constantele declarate cu const trebuie s fie ini ializate la declararea
lor.

Exemplul 1:

const int x; //gresit, constanta nu a fost initializata


const int x = 13; //corect

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:

readonly int x; //corect


readonly int x = 13; //corect

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;

I.2.4.6. Expresii i operatori

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:

Prioritate Tip Operatori Asociativitate


0 Primar ( ) [ ] f() . x++ x-- new typeof sizeof
checked unchecked ->
1 Unar + - ! ~ ++x --x (tip) true false & sizeof
2 Multiplicativ * / %
3 Aditiv + -
4 De deplasare << >>
5 Rela ional < > <= >= is as
6 De egalitate == !=
7 AND (SI) logic &
8 XOR (SAU exclusiv) ^
logic
9 OR (SAU) logic |
10 AND (SI) &&
condi ional
11 OR (SAU) ||
condi ional
12 Condi ional(ternar) ?:
13 atribuire simpl =
atribuire compus *= /= %= += -= ^= &= <<= >>= |=

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();
}
}
}

În urma rul rii programului ob inem:

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();
}
}
}

I.2.4.7. Op iuni de afi are

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

unde „sir” este format din dou elemente:


caracterele afi abile obi nuite con inute în mesaje

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

În C# exist dou tipuri de conversii numerice:


implicite
explicite.
Conversia implicit se efectueaz (automat) doar dac nu este afectat valoarea convertit .

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

I.2.4.8.2. Conversia explicit

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 urma rul rii programului, se va ob ine:

Î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);

strrez = Convert.ToString(bv) + Convert.ToString(frez);


Console.WriteLine("bool si float spre string folosind ToString
\"{0}\" + \"{1}\" = {2}", bv, frez, strrez);

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:

Prin boxing, variabila i este asignata unui obiect ob:


int i = 13;
object ob = (object)i; //boxing explicit

sau
int i = 13;
object ob = i; //boxing implicit

În prima linie din exemplu se declar i se stiva heap


ini ializeaz o variabil de tip valoare, care va con ine i
valoarea 13, valoare care va fi stocat pe stiv . Linia a 13
int i=13;
doua creeaz o referin c tre un obiect alocat în heap,
care va con ine atât valoarea 13, cât i informa ia ob
int
referitoare la tipul de dat con inut. object ob=i; 13

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");
}

Prin boxing se creeaz o copie a valorii care va fi con inut .

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();
}
}
}

În urma rul rii se ob ine:

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

Pentru conversia invers , adic din ir de caractere în num r, sintaxa este:


ir int int.Parse( ir) sau Int32.Parse( ir)
ir long long.Parse( ir) sau Int64.Parse( ir)
ir double double.Parse( ir) sau Double.Parse( ir)
ir float float.Parse( ir) sau Float.Parse( ir)

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

Console.WriteLine("{0}\t{1}\tdouble", "3.1415", d2);


Console.ReadKey();
}
}
}

I.2.5. Tipuri de date

În C# exist dou categorii de tipuri de date:


tipuri valoare
- tipul simplu predefinit: byte, char, int, float etc.
- tipul enumerare – enum
- tipul structur - struct
tipuri referin
- tipul clas – class
- tipul interfa – interface
- tipul delegat – delegate
- tipul tablou - array
24
Observa ie: Toate tipurile de date sunt derivate din tipul System.Object
Toate tipurile valoare sunt derivate din clasa System.ValueType, derivat la rândul ei
din clasa Object (alias pentru System.Object).
Pentru tipurile valoare, declararea unei variabile implic i alocarea de spa iu. Dac
ini ial, variabilele con in valoarea implicit specific tipului, la atribuire, se face o copie a datelor în
variabila destina ie care nu mai este legat de variabila ini ial . Acest proces se nume te
transmitere prin valoare, sau value semantics.

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();
}
}
}

I.2.5.1. Tipul valoare

I.2.5.1.1. Tipuri predefinite

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

Tip Descriere Alias pentru tipul struct


din spa iul de nume System
object r d cina oric rui tip
string secven de caractere Unicode System.String
sbyte tip întreg cu semn, pe 8 bi i System.Sbyte
short tip întreg cu semn, pe 16 bi i System.Int16
int tip întreg cu semn pe, 32 bi i System.Int32
long tip întreg cu semn, pe 64 de bi i System.Int64
byte tip întreg f r semn, pe 8 bi i System.Byte
ushort tip întreg f r semn, pe 16 bi i System.Int16
uint tip întreg f r semn, pe 32 bi i System.Uint32
ulong tip întreg f r semn, pe 64 bi i System.Uint64
float tip cu virgul mobil , simpl precizie, pe 32 bi i System.Single
(8 pentru exponent, 24 pentru mantis )
double tip cu virgul mobil , dubl precizie, pe 64 bi i System.Double
(11 pentru exponent, 53 pentru mantis )
bool tip boolean System.Boolean
char tip caracter din setul Unicode, pe 16 bi i System.Char
decimal tip zecimal, pe 128 bi i (96 pentru mantis ), 28 System.Decimal
de cifre semnificative

Domeniul de valori pentru tipurile numerice:

Tip Domeniul de valori


sbyte -128; 127
short -32768; 32767
int -2147483648; 2147483647
long -9223372036854775808; 9223372036854775807
byte 0; 255
ushort 0; 65535
uint 0; 4294967295
ulong 0; 18446744073709551615
float -3.402823E+38; 3.402823E+38
double -1.79769313486232E+308; 1.79769313486232E+308
decimal -79228162514264337593543950335;
79228162514264337593543950335

O valoare se asigneaz dup urm toarele reguli:

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:

string s = “Salut!” float g = 1.234F;


long a = 10; double h = 1.234;
long b = 13L; double i = 1.234D;
ulong c = 12; bool cond1 = true;
ulong d = 15U; bool cond2 = false;
ulong e = 16L; decimal j = 1.234M;
ulong f = 17UL;

I.2.5.1.2. Tipul enumerare

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:

[atribute][modificatori]enum NumeEnumerare [: Tip]


{
lista
}

În ceea ce urmeaz , vom considera enum f r elementele op ionale.


Folosirea tipului enumerare impune urm toarele observa ii:
în mod implicit, valoarea primului membru al enumer rii este 0, iar fiecare variabil care
urmeaz are valoarea (implicit ) mai mare cu o unitate decât precedenta.
valorile folosite pentru ini ializ ri trebuie s fac parte din domeniul de valori al tipului
enum
nu se admit referin e circulare
enum ValoriCirculare
{
a = b,
b
}

În acest exemplu, a depinde explicit de b, iar b depinde de a implicit

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();
}
}
}

I.2.5.1.3. Tipuri nulabile

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.

I.2.6. Instruc iuni condi ionale, de itera ie i de control

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.

Punctele M1(x1,y1), M2(x2,y2), M3(x3,y3) sunt coliniare


x1 y1 1
x2 y2 1 = 0
x3 y3 1
E=(x2-x1)(y3-y1)-(x3-x1)(y2-y1)=0

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());

double E = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);

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());

ux = x % 10; // ma intereseaza doar ultima cifra


Console.Write("Ultima cifra a lui {0} la puterea {1} este : ", x,
n);

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

Instruc iunea while are sintaxa:

while (conditie) Instructiuni;

Cât timp conditie este îndeplinit se execut Instructiuni.

Exemplul 28: S se afi eze numerele întregi pozitive <= 10

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;
}
}
}

I.2.6.4. Instruc iunea do – while

Instruc iunea do – while are sintaxa:

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;
}
}
}

I.2.6.5. Instruc iunea for

Instruc iunea for are sintaxa:

for(initializareCiclu; conditieFinal; reinitializareCiclu)


Instructiune

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;
}
}
}

Exemplul 36: Un exemplu de for pe numere reale.

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:

string[] nume = {"Ana", "Ionel", "Maria"}

Afi area irului folosind for:

for(int i=0; i<nume.Length; i++)


Console.Write("{0} ", nume[i]);

Acela i rezultat îl ob inem folosind instruc iunea foreach:

foreach (string copil in nume)


Console.Write("{0} ", copil);

Mai d m înc un exemplu de folosire a lui foreach:

string s="Curs"+" de"+" informatica";


foreach(char c in s)
Console.Write(c);

Exemplul 37: S se împart un ir de caractere în cuvinte. Se va afi a num rul de cuvinte i


fiecare cuvânt în parte

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;
}

I.2.6.8. Instruc iunea continue

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();
}
}
}

I.2.6.9. Instruc iunile try-catch-finally i throw

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

throw new System.Exception();

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");
}
}
}

Încercând s compil m ob inem:

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();
}
}
}
}

Bineîn eles c în blocul catch putem s scriem ce cod dorim, de exemplu:

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

I.2.7.1. Tablouri unidimensionale

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:

nume = new Tip[NumarElemente];

Se pot face în acela i timp opera iile de declarare, instan iere i ini ializare:

Exemplu:

int[] v = new int[] {1,2,3);

sau

int[] v = {1,2,3);

Exemplul 41: Crearea, sortarea i afi area unui vector:

int[] v = new int[5] { 10, 2, 4, 8, 6 };


Array.Sort(v); //sortarea crescatoare a vectorului v

for (int i = 0; i < v.Length; i++) //afisarea vectorului v


Console.Write("{0,3}", v[i]);

Afi area se poate face i cu ajutorul lui foreach:

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;
}
}
}

I.2.7.2. Tablouri multidimensionale

Î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;

iar instan ierea:

nume = new Tip[Linii,Coloane];

Accesul:

nume[indice1,indice2]

58
Exemplu: Declararea instan ierea i ini ializarea

int[,] mat = new int[,] {{1,2,3},{4,5,6},{7,8,9}};

sau

int[,] mat = {{1,2,3},{4,5,6},{7,8,9}};

În cazul tablourilor neregulate (jagged array) declararea se face:

Tip [][] nume; //tablou neregulat cu doua


//dimensiuni

iar instan ierea i ini ializarea:

Tip [][] nume = new Tip[][]


{
new Tip[] {sir_0},
new Tip[] {sir_1},
...
new Tip[] {sir_n}
};

sau

Tip [][] nume = {


new Tip[] {sir_0},
new Tip[] {sir_1},
...
new Tip[] {sir_n}
};

Acces

nume[indice1][indice2]

59
Exemple:

int[][] mat = new int[][]


{
new int[3] {1,2,3},
new int[2] {4,5},
new int[4] {7,8,9,1}
};

sau

int[][] mat = {
new int[3] { 1, 2, 3 },
new int[2] { 4, 5 },
new int[4] { 7, 8, 9, 1 }
};

Observa ie: Este posibil declararea vectorilor de dimensiuni mai mari.

Exemple:

int[, ,] vect = new int[2, 3, 5];

int[, , ,] vect = new int[6, 2, 4, 8];

Vectorii 3-D sunt utiliza i frecvent în aplica iile grafice.

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.

string a = "Acesta este un sir de caractere";


string b = "";
string nume = "Gigel";

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 ele escape permit reprezentarea caracterelor care nu au reprezentare grafic


precum i reprezentarea unor caractere speciale: backslash, caracterul apostrof, etc.

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

Pentru a concatena iruri de caractere folosim operatorul “+”

Exemplu:

string a = "Invat " + "limbajul " + "C#";


//a este "Invat limbajul C#"

1.2.8.2. Compararea irurilor de caractere

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

Exemplul 51: Exemplific m aplicarea func iilor de mai sus:

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());
}
}
}

Exemplul 52: Programul urm tor contorizeaz majusculele dintr-un text.

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

I.2.9.1. Administrarea fi ierelor

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.

I.2.9.2. Scrierea i citirea datelor din fi iere text

Fi ierele de ie ire necesit utilizarea unui obiect StreamWriter.


Func ia CreateText(), ce face parte din clasa File, deschide un fi ier i creeaz obiectul
StreamWriter.

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();
}

}
}

I.2.9.3. Scrierea i citirea datelor din fi iere binare

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

I.3.1. Evolu ia tehnicilor de programare

Programarea nestructurat (un program simplu, ce utilizeaz numai variabile globale);


complica iile apar când prelucrarea devine mai ampl , iar datele se multiplic i se diversific .
Programarea procedural (program principal deservit de subprograme cu parametri
formali, variabile locale i apeluri cu parametri efectivi); se ob in avantaje privind depanarea i
reutilizarea codului i se aplic noi tehnici privind transferul parametrilor i vizibilitatea variabilelor;
complica iile apar atunci când la program sunt asigna i doi sau mai mul i programatori care nu pot
lucra simultan pe un acela i fi ier ce con ine codul surs .
Programarea modular (gruparea subprogramelor cu func ionalit i similare în module,
implementate i depanate separat); se ob in avantaje privind independen a i încapsularea (prin
separarea zonei de implementare, p strând vizibilitatea numai asupra zonei de interfa a
modulului) i se aplic tehnici de asociere a procedurilor cu datele pe care le manevreaz ,
stabilind i diferite reguli de acces la date i la subprograme.
program principal
date

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.

I.3.2. Tipuri de date obiectuale. Încapsulare

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.

Considerând, în rezolvarea unei probleme de gestiune a accesului utilizatorilor la un anumit


site, tipul abstract USER, vom observ c sunt multe date ce caracterizeaz un utilizator Internet.
Totu i se va ine cont doar de datele semnificative pentru problema dat . Astfel, „culoarea ochilor”
este irelevant în acest caz, în timp ce „data na terii” poate fi important . În aceea i idee, opera ii
specifice ca „se înregistreaz ”, „comand on-line” pot fi relevante, în timp ce opera ia „m nânc ”
nu este, în cazul nostru. Evident, nici nu se pun în discu ie date sau opera ii nespecifice („num rul
de laturi” sau ac iunea „zboar ”).

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.

Folosirea unui tip de date obiectual tip presupune:


existen a defini iei acestuia
apelul metodelor
accesul la date.

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 .

Defini ie: Ca i în Java, în C# o subclas poate mo teni de la o singur superclas , adic


avem de-a face cu mo tenire simpl ; aceea i superclas îns poate fi derivat în mai multe
subclase distincte. O subclas , la rândul ei, poate fi superclas pentru o alt clas derivat . O
clas de baz împreun cu toate clasele descendente (direct sau indirect) formeaz o ierarhie de
clase. În C#, toate clasele mo tenesc de la clasa de baz Object.

În contextul mecanismelor de mo tenire trebuie aminti i modificatorii abstract i sealed


aplica i unei clase, modificatori ce oblig la i respectiv se opun procesului de derivare. Astfel, o clas
abstract trebuie obligatoriu derivat , deoarece direct din ea nu se pot ob ine obiecte prin opera ia
de instan iere, în timp ce o clas sigilat (sealed) nu mai poate fi derivat (e un fel de terminal în
ierarhia claselor).

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 .

I.3.5. Polimorfism. Metode virtuale

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 .

I.3.6. Principiile program rii orientate pe obiecte

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.

Principiile POO sunt:


1. abstractizarea - principiu care permite identificarea caracteristicilor i comportamentului
obiectelor ce in nemijlocit de domeniul problemei. Rezultatul este un model. În urma
abstractiz rii, entit ilor din domeniul problemei se definesc prin clase.
2. încapsularea – numit i ascunderea de informa ii, este caracterizat prin 2 aspecte:
a. Gruparea comportamentelor i caracteristicilor într-un tip abstract de date
b. Definirea nivelului de acces la datele unui obiect
3. mo tenirea – organizeaz i faciliteaz polimorfismul i încapsularea permi ând definirea
si crearea unor clase specializate plecând de la clase (generale) care sunt deja definite -
acestea pot împ rt i ( i extinde) comportamentul lor f r a fi nevoie de redefinirea
aceluia i comportament.
4. Polimorfismul - posibilitatea mai multor obiecte dintr-o ierarhie de clase de a utiliza
denumiri de metode cu acela i nume dar, cu un comportament diferit.

I.4. Structura unei aplica ii orientat pe obiecte în C#

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

I.4.1. Clas de baz i clase derivate

S definim o clas numit Copil:

public class Copil { }

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

public class Fetita: Copil { }


public sealed class Baiat: Copil { }

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

Înainte de a continua amintim câteva no iuni legate de constructorii unei clase:


Constructorul este o func ie care face parte din corpul unei clase. Corpul constructorului este format
din instruc iuni care se execut la crearea unui nou obiect al clasei respective (sau la crearea clasei,
în cazul constructorilor cu modificatorul static).
pot exista mai mul i constructori care se pot diferen ia prin lista lor de parametri
constructorii nu pot fi mo teni i
dac o clas nu are definit niciun constructor, se va asigna automat constructorul f r
parametri al clasei de baz (clasa object, dac nu este precizat clasa de baz )

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.

Relu m exemplu de mai sus în care vom prezenta un constructor f r parametri i


constructorul implicit din clasa derivat . Vom ad uga un constructor f r parametri. La ini ializarea
obiectului se va citi de la tastatur un ir de caractere care va reprezenta numele copilului.

Exemplul 60:

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( );
}
}

class Fetita: Copil


{ }
...
Fetita f = new Fetita ( );
Copil c = new Copil ( );

I.4.3. Supraînc rcarea constructorilor i definirea constructorilor în


clasele derivate

Relu m exemplul anterior i îl dezvolt m:

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();
}

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
}
}

Fetita c = new Fetita();


Copil.adaug_copil(c);
//referin a noului obiect se memoreaz în tabloul static copii
//(caracteristic clasei) i se incrementeaz data static nr_copii
Baiat c = new Baiat();
Copil.adaug_copil(c);
Copil c = new Copil();
Copil.adaug_copil(c);
Copil.afisare(); //se afi eaz o list cu numele celor 3 copii

...

Definirea datelor i metodelor nestatice corespunz toare clasei Copil i claselor derivate

Exemplul 62:

85
public class Copil
{
protected string nume;
...

public virtual void se_joaca( ) //virtual – functia se poate


{ //suprascrie la derivare
Console.WriteLine("{0} se joaca.", this.nume);
}
public void se_joaca(string jucaria) //supradefinirea metodei
{ //se_joaca
Console.WriteLine("{0} se joaca cu {1}.",this.nume,jucaria);
}

...
}
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:

public class Copil


{...
string nume; // este implicit protected
public string Nume //proprietatea Nume
{ get
{ if(char.IsUpper(nume[0]))
return nume;
else
return nume.ToUpper();
}
set
{
nume = value;
}
}
public Copil() //metoda set
{
Nume = Console.ReadLine( );
}
}

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.

În proiectarea unei aplica ii POO parcurgem urm toarele etape:


1. identificarea entit ilor, adic a obiectelor care apar în domeniul aplica iei, prin
eviden ierea substantivelor din enun ul problemei
2. pentru fiecare obiect se identific datele i opera iile, prin eviden ierea verbelor i
adjectivelor care caracterizeaz subiectul respectiv
3. identificarea rela iilor dintre entit i
4. crearea unei ierarhii de clase, pornind de la aceste entit i

87
5. implementarea claselor i a sistemului
6. testarea i punerea la punct.

I.5. Clase i obiecte

I.5.1. Clase

Clasele reprezint tipuri referin definite de utilizator.

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

identificator - este numele clasei

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

Atât datele cât i func iile pot avea ca modificatori de acces:

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.

Declararea datelor se face:

[modificatorAcces] tipData nume;

unde:

modificatorAcces - este op ional. Implicit este private.


tipData - reprezint tipul datei obiectului pe care vrem s -l atribuim.
nume - se refer la numele dat de utilizator obiectului respectiv.

Datele pot fi:


constante,
câmpuri.

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:

[modificator] const tip identificator = expresieConstanta

[modificator] const tip identificator = expresieConstanta

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:

tip identificator [=valoare]

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

Pentru a declara un câmp readonly se va folosi cuvântul readonly în declara ia sa.


Atribuirea se face doar la declararea sa, sau prin intermediul unui constructor:

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
}

În momentul compil rii valoarea câmpului readonly nu se presupune a fi cunoscut .

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

Ini ializarea câmpurilor

Valorile implicite pe care le iau câmpurile la declararea lor sunt:

tip valoare
numeric 0
bool false
char \0
enum 0
referin null

I.5.1.(2) Func ii

Func iile pot fi:


Constructori
Destructori
Metode
Propriet i
Evenimente
Indexatori
Operatori

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();
}

Exemplul 69: Constructor cu doi parametri

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();
}
}
}

Observa ie: Constructorii nu pot fi mo teni i.

I.5.1.(4) Destructori

Destructorul clasei implementeaz ac iunile necesare distrugerii unei instan e a clasei.


Numele destructorului coincide cu numele clasei, fiind precedat de caracterul „~”. Destructorul nu
are parametri i nici modificator de acces. Destructorul este apelat automat. Într-o clas exist un
singur destructor. Destructorul nu poate fi mo tenit.

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:

modificatorAcces tipReturnat numeMetoda([parametri])


[{
corp_Metoda
}]

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:

[atribut][modificator] tip nume

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.

Un parametru formal special este parametrul tablou cu sintaxa:

[atribut] params tip [ ] nume

Pentru metodele abstracte i externe, corpul metodei se poate reduce la un semn ;

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 .

La apelul metodei, orice parametru trebuie s aib acela i modificator ca la definire

Invocarea unei metode se realizeaz prin:


[nume_obiect].[nume_metoda] pentru metodele nestatice
[nume_clas ].[nume_metoda] pentru metodele statice

97
I.5.1.2.4. Propriet i

Proprietatea este un membru al clasei care ne permite s accedem sau s modific m


caracteristicile unui obiect sau al clasei.

Sintaxa este:

[atribut]modificatorAcces tipReturnat numeProprietate


{
get
{
}
set
{
}
}

unde:

modificatorAcces - poate fi orice modificatorAcces amintit, precum i new,


static, virtual, sealed, override, abstract, extern.

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();

//linia urmatoare apeleaza accesorul


//'set' din proprietatea P si ii
//paseaza 10 lui ‘value’

obiect.P = 10;

int xVal = obiect.P;

// linia urmatoare apeleaza accesorul


//'get' din proprietatea P

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.

Tehnica prin care clasele implementeaz metode (handler-e) ce r spund la evenimente


generate de alte clase poart numele de tratare a evenimentelor.

Sintaxa:

[atribut][modificatorAcces]even tipDelegat nume

unde:

modificatorAcces - este la fel ca în cazul metodelor


tipDelegat – este un tip de date, derivat din clasa sigilat Delegate din spa iul System.

Definirea unui tipDelegat se realizeaz astfel:

[atribut][modificatorAcces] delegate tipRezultat nume[listaParametri])

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:

tipReturnat this [listaParametrilorFormali]

unde:
listaParametrilorFormali – trebuie s con in cel pu in un parametru, parametru care nu trebuie s
fie de tipul ref sau out.

declaratiiDeAccesor – asem n toare cu cele de la propriet i, trebuie s con in accesorul get


sau accesorul set.

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:

[atribut] modificatorOperator declaratieDeOprator corpOperator

Observa ia 1: Operatorii trebuiesc declara i publici sau statici.


Observa ia 2: Parametrii operatorilor trebuie s fie de tip valoare. Nu se admit parametri de
tip ref sau out.

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 :

tip operatorUnarSupraînc rcabil (tip identificator) corp

Operatorii unari supraînc rcabili sunt: + - ! ˜ ++ – true false.


Reguli pentru supraînc rcarea operatorilor unari:
Fie T clasa care con ine defini ia operatorului
1. Un operator + - ! ˜ poate returna orice tip i preia un singur parametru de tip T
2. Un operator ++ sau –- trebuie s returneze un rezultat de tip T i preia un singur parametru
de tip T
3. Un operator unar true sau false returneaz bool i trebuie s preia un singur
parametru de tip T. Operatorii true i false trebuie s fie ambii defini i pentru a prevenii o
eroare de compilare.
Exemplul 77:

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;
}

public void Afis()


{
Console.WriteLine("{0} {1}i", x, y);
}

public static Complex operator -(Complex c)


{
Complex temp = new Complex();
temp.x = -c.x;
temp.y = -c.y;
return temp;
}
}

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

Supraînc rcarea operatorilor binari are urm toarea sintax :

tip operator operatorBinarSupraînc rcabil (tip identificator,


tip identificator) corp

Operatorii binari supraînc rcabili sunt: + - * / & | ^ << >> == != > < >= <=

Reguli pentru supraînc rcarea operatorilor binari:

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);
}

public static Complex operator +(Complex c1, Complex c2)


{
Complex temp = new Complex();
temp.x = c1.x + c2.x;
temp.y = c1.y + c2.y;
return temp;
}
}

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:

implicit operator tip(tip parametru) corp


explicit operator tip(tip parametru) corp

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.

La instan ierea clasei trebuie s declar m tipul datelor utilizate.

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;

public void Push(TipElement data)


{
// code corespunzator introducerii de elemente
}

public TipElement Pop()


{
// code corespunzator extragerii de elemente
}
}

Stiva<char> StivaMea = new Stiva<char>();


StivaMea.Push("a");
char x = StivaMea.Pop();

Exemplul 82: tipurile parametrizate pot fi aplicate claselor i interfe elor

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 83: tipurile parametrizate se pot aplica metodelor


class clA
{
public void methode1<T>()
{
}
public T[] methode2<T>()
{
return new T[10];
}
}

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();
}
}
}

Implementarea sufer de câteva probleme:


elementele clasei Stiva trebuie s fie convertite explicit
atunci când se folose te clasa Stiva cu elemente de tip valoare, se realizeaz implicit o
opera ie de boxing cu inserarea unui element i o opera ie de tip unboxing cu recuperarea unui
element
dorim s introducem în stiv elemente de tipuri diferite în aceea i instan a clasei Stiva.
Acest lucru va duce la probleme de convertire care vor fi descoperite la execu ie

Deoarece problema conversiei nu este detectat la compilare, va produce o excep ie la


execu ie. Din acest motiv spunem: codul nu este type-safe.

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.

C# ne permite rezolvarea unor astfel de probleme introducând tipurile generice. Concret


putem implementa o list de elemente de tip T, l sând libertatea utilizatorului s specifice tipul T la
instan ierea clasei.

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();
}
}
}

I.7. Derivarea claselor (mo tenire)

I.7.1. Principiile mo tenirii

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 .

Definirea unei clase derivate se face folosind sintaxa:

class ClasaDerivata : ClasaDeBaza


{

}

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

În contextul mecanismelor de mo tenire trebuie aminti i modificatorii abstract i sealed aplica i


unei clase, modificatori ce oblig la i respectiv se opun procesului de derivare. Astfel, o clas
abstract trebuie obligatoriu derivat , deoarece direct din ea nu se pot ob ine obiecte prin opera ia
de instan iere, în timp ce o clas sigilat (sealed) nu mai poate fi derivat (e un fel de terminal în
ierarhia claselor). 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 . O metod sigilat nu mai poate
fi redefinit în clasele derivate din clasa curent .

Muzician clasa de baz (clasa general )

Violonist clasa derivat (clasa specializat )

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();
}
}
}

I.7.2. Accesibilitatea membrilor mo teni i

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";
}

class ClasaDerivata : ClasaDeBaza


{
public string sir = "Sir din clasa derivata";
public void afis()
{
Console.WriteLine("{0}", sir);
Console.WriteLine("{0}", base.sir);
}
}

static void Main(string[] args)


{
ClasaDerivata cd = new ClasaDerivata();
cd.afis();
Console.ReadLine();
}
}
}

I.7.2.(1) Utilizarea cuvântului cheie protected

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.

I.7.3. Apelul constructorilor clasei de baz

Exemplul 88:

117
class ClasaDeBaza
{
protected string var;
public ClasaDeBaza(string var) //constructor
{
this.var = var;
}
}

clasa Derivata : ClasaDeBaza


{
public ClasaDeBaza(string var) : base(var)
{
...
}
}

I.7.3. Metode

Prin mecanismul de mo tenire avem posibilitatea reutiliz rii codului i redefinirii (prin
polimorfism) a metodelor.

I.7.3.(1) Virtual i override

O clas declarat virtual implic faptul c o metod implementat în ea poate fi redefinit în


clasele derivate.
Doar metodele virtuale ne statice i/sau private pot fi redefinite într-o clas derivat . Aceste
metode trebuie s aib aceea i signatur (nume, modificator de acces, tip returnat i parametri).
Pentru declararea unei metode ca fiind virtual se folose te cuvântul cheie virtual. În clasele
derivate se va folosi cuvântul cheie override pentru redefinirea metodei virtuale din clasa de baz .

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

Imobiliara Bun Depunere Investi ie Credit_primit

Teren B_inchiriat Actiune

Productiv Mobilier Cot

Neproductiv Altul Credit_acordat

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();

I.8. Tratarea excep iilor în C#

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

Ierarhia excep iilor


121
Dintre metodele i propriet ile clasei Exception amintim:

Metodele i propriet ile clasei Exception Explica ii


sunt constructori
public Exception( )
public Exception (string)
public Exception (string, Exception) observ m c o excep ie poate
con ine în interiorul s o instan a
unei alte excep ii
public virtual string HelpLink {get; set} ob ine sau seteaz o leg tur c tre
fi ierul Help asociat excep iei, sau
c tre o adres Web
public Exception InnerException {get;} returneaz excep ia care este
încorporat în excep ia curent
public virtual string Message {get;} ob ine un mesaj care descrie excep ia
curent
public virtual string Source {get; set;} ob ine sau seteaz numele aplica iei
sau al obiectului care a cauzat
eroarea
public virtual string StackTrace {get;} ob ine o reprezentare de tip string a
apelurilor de metode care au dus la
apari ia excep iei
public MethodBase TargetSite {get;} ob ine metoda care a aruncat
excep ia curent

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

I.8.1.(1) Blocurile try i catch

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

S analiz m pu in programul de mai sus:


Dac liniile (2) i (3) nu sunt comentate, în urma execu ii programului, respectivele linii afi eaz
informa ii despre excep iile ap rute.
Liniile (1) i (4) au fost puse pentru a personaliza informa iile referitoare la excep iile ap rute.
Linia (5) a fost pus în program pentru a demonstra rularea f r probleme, în cazul în care
blocurile catch exist . Încerca i s comenta i unul dintre blocurile catch, introduce i date care
s produc excep ia pe care blocul comentat ar trata-o i ve i observa întreruperea, cu mesaj
de eroare a rul rii programului.

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.

I.8.1.(2) Instruc iunea throw

Programatorul poate s - i compun modalit i proprii de aruncare a erorilor folosind


instruc iunea throw:

throw new NumeExceptie(exceptie);

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");
}
}
}

S analiz m programul de mai sus:


Dac coment m liniile (1), (2), (3), (4), (5), (6), (7) i la rularea programului introducem un
num r în loc de o cifr , programul se opre te din execu ie, iar ca mesaj apare irul definit de
utilizator în linia (0)

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

În Capitolul 3 defineam no iunea de polimorfism, 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.

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

I.9.2. Polimorfismul parametric

Aceast form de polimorfism este preluat de la limbajele neobiectuale: Pascal, C. Prin


aceast form de polimorfism, o func ie va prelucra orice num r de parametri. Pentru aceasta se
va folosi un parametru de tip params.

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.

I.9.5. Modificatorii virtual i override

În cazul în care se dore te ca apelul metodelor s se fac la rulare i nu la compilare vom


reconsidera exemplul anterior în care func ia Afis( ) din clasa de baz o declar m virtual , iar
func ia Afis( ) din clasa derivat o consider m ca suprascriere a lui Afis( ) din clasa de baz :
Exemplul 96:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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.

II. Programare vizual

II.1. Concepte de baz ale program rii vizuale

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

Realizarea unei aplica ii vizuale nu const doar în desenare i aranjare de controale, ci


presupune în principal stabilirea unor decizii arhitecturale, decizii ce au la baz unul dintre
modelele arhitecturale de baz .

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

Mediul de dezvoltare Microsoft Visual C# dispune de instrumente specializate de


proiectare, ceea ce permite crearea aplica iilor în mod interactiv, rapid i u or.
Pentru a construi o aplica ie Windows (File New Project) se selecteaz ca template
Windows Forms Application.

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.

II.3. Elementele POO în context vizual

În cele ce urmeaz pentru explica iile care vor avea loc vom considera o aplica ie Windows
numit Test:

În urma gener rii proiectului Test avem:

136
Fereastra Toolbox Fereastra Windows Forms
Designer în care s-a creat Fereastra Solution
Form1 Explorer

Fereastra pentru Fereastra Properties


afi arearea Listei de
erori

Bara de unelte Bara de meniuri

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

Implicit, la crearea unui proiect windows, apar dou bare de instrumente

Prima bar de unelte

unde:

Icoana Semnifica ie
proiect nou (Ctrl+Shift+A)

138
Icoana Semnifica ie

ad ugare de noi itemi (Ctrl+Shift+A)


deschide fi ier (Ctrl+O)

salveaz Form1.cs (Ctrl+S)

salveaz tot proiectul (Ctrl+Shift+O)

cut (Ctrl+X)

copy (Ctrl+C)

paste (Ctrl+V)

undo (un pas înapoi) (Ctrl+Z)

redo (un pas înainte) (Ctrl + Y)

navigare înapoi în cod sau ferestre (Ctrl + -)

navigare înainte în cod sau ferestre (Ctrl + Shift -)

Start debugging (F5) Compileaz proiectul i-l lanseaz în modul debug

Solution Configuration

Solution Platform

c utare i înlocuire (Ctrl + Shift + F)

139
Icoana Semnifica ie
fereastra pentru c utare

fereastra Solution Explorer (Ctrl + W, S)

fereastra Properties (Ctrl + W, P)

fereastra Object Browser (Ctrl + W, J)

fereastra Toolbox (Ctrl + W, X)

fereastra de start Start Page

fereastra Document Outline (Ctrl + W, U)

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

Revenind la fereastra Toolbox. Putem s


deschidem una dintre op iunile din fereastr ap sând
semnul plus din fa . De exemplu, dac deschidem
Common Controls în fereastr apar controale mai des
folosite. Orice control poate fi adus pe Form-ul nostru (îi
vom putea spune, în egal m sur , fereastr , interfa ,
formular) prin dublu clic pe respectivul control, sau prin
drag and drop în Form.

140
Fereastra Solution Explorer

Vom observa c în momentul în care d m clic


pe Form sau pe un control, fereastra din dreapta,
Properties, se va referi la acesta control sau aceast
fereastr .

Fereastra Solution Explorer, din partea


dreapt se refer , printre altele la ferestra Designer
sau la fereastra în care utilizatorul va scrie propriul
cod.

În cazul în care fereastra Designer este închis ,


putem apela la op iunea Open i va reap rea în
fereastra central . Dac dorim s vedem codul,
ap s m pe op iunea View Code, iar în fereastra
principal se va deschide, înc o ferestr
corespunz toare codului dorit.
Acela i lucru îl putem spune i despre
Properties.cs, din aceea i fereastr .

În toate cazurile men ionate mai sus, pentru a


ob ine efectul afi at i în imagini, se va ac iona
butonul din dreapta al mouse-ului.

Despre op iunile care apar în cazul în care d m


clic dreapta pe Test, vom discuta, la modul concret, în
unele dindre exemplele are urmeaz

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:

Proprietatea Descrierea propriet ii


Anchor se refer la posibilitatea de a ancora controlul fa de o margine (sau
toate)
BackColor permite stabilirea culorii de fundal a controlului
Bottom permite stabilirea distan ei dintre marginea de sus a ferestrei i control
Dock ata eaz controlul la una dintre marginile ferestrei
Enabled permite controlului s recep ioneze evenimente de la utilizator
ForeColor permite stabilirea culorii textului
Height permite definirea în l imii controlului
Left permite stabilirea distan ei dintre marginea din stânga a ferestrei i
marginea stânga a controlului
Name permite denumirea controlului pentru a-l putea mai u or vizualiza i
manipula în codul surs
Parent p rintele controlului
Right permite stabilirea distan ei dintre marginea din dreapta a ferestrei i
marginea din dreapta a controlului
TabIndex prin num rul de ordine care i se ata eaz se stabile te ordinea activ rii
controlului la ap sarea tastei TAB
TabStop permite sau nu ca respectivul control s fie activat prin ap sarea tastei
TAB
Tag se refer la un ir de caractere pe care controlul îl poate stoca în interiorul
s u
Top permite stabilirea distan ei dintre marginea de sus a ferestrei i marginea
de sus a controlului
Visible stabile te dac respectivul control, care exit în fereastr , este (TRUE)
sau nu vizibil
Width stabile te l imea controlului

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:

Evenimentul Descrierea evenimentului


Clic se genereaz când se d clic asupra unui control
DoubleClic se genereaz când se d dublu clic asupra unui control. Excep ie f când
Button asupra c ruia nu se va putea face dublu clic, deoarece controlul
ac ioneaz la primul clic
DragDrop se genereaz la finalizarea lui drag and drop

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. Construirea interfe ei utilizator

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

O fereastr poate fi activat cu form.Show() sau cu form.ShowDialog(), metoda a doua


permi ând ca revenirea în fereastra din care a fost activat noul formular s se fac numai dup ce
noul formular a fost închis (spunem c formularul nou este deschis modal).

Un propietar este o fereastr care contribuie la comportarea formularului de inut. Activarea


propietarului unui formular deschis modal va determina activarea formularului deschis modal. Când
un nou formular este activat folosind form.Show() nu va avea nici un de in tor, acesta stabilindu-
se direct :

public Form Owner { get; set; }


F_nou form=new F_nou();
form.Owner = this; form.Show();

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.

F_nou form = new F_nou();


form.ShowDialog(this);

Vizibilitatea unui formular poate fi setat folosind metodele Hide sau Show. Pentru a
ascunde un formular putem folosi :

this.Hide(); // setarea propietatii Visible indirect sau


this.Visible = false; // setarea propietatii Visible direct

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

HelpButton-precizeaz dac butonul va ap rea sau nu lâng butonul de închidere al


formularului (doar dac MaximizeBox=false, MinimizeBox=false). Dac utilizatorul apas acest
buton i apoi apas oriunde pe formular va ap rea evenimentul HelpRequested (F1).
Icon reprezint un obiect de tip *.ico folosit ca icon pentru formular.
MaximizeBox i MinimizeBox precizeaz dac fereastra are sau nu butonul Maximize i
respectiv Minimize
Opacity indic procentul de opacitate

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

Dac în Designer efectu m dublu clic pe un control, se va genera automat o func ie de


tratare pentru evenimentul implicit asociat controlului (pentru un buton evenimentul implicit este
Clic, pentru TextBox este TextChanged, pentru un formular Load etc.).

Printre evenimentele cele mai des utilizate, se num r :


Load apare când formularul este pentru prima data înc rcat în memorie.
FormClosed apare când formularul este închis.
FormClosing apare când formularul se va inchide ca rezultat al ac iunii utilizatorului asupra
butonului Close (Dac se seteaz CancelEventArgs.Cancel =True atunci se va opri închiderea
formularului).
Activated apare pentru formularul activ.
Deactivate apare atunci când utilizatorul va da clic pe alt formular al aplicatiei.

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.

Un control este o instan a unei clase derivate din System.Windows.Forms i este


reponsabil cu desenarea unei p r i din container. Visual Studio .NET vine cu o serie de controale
standard, disponibile în Toolbox. Aceste controale pot fi grupate astfel:

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.

Func ia Numele Descriere


controlului controlului
buton Button Sunt folosite pentru a executa o secven de instruc iuni în
momentul activ rii lor de c tre utilizator
calendar MonthCalendar Afi eaz implicit un mic calendar al lunii curente. Acesta
poate fi derulat i înainte i înapoi la celelalte luni
calendaristice.
caset de CheckBox Ofer utilizatorului op iunile : da/nu sau include/exclude
validare
etichet Label Sunt folosite pentru afi area etichetelor de text, i a pentru a
eticheta controalele.
caset cu ListBox Afi eaz o list de articole din care utilizatorul poate alege.
list
imagine PictureBox Este folosit pentru ad ugarea imaginilor sau a altor resurse
de tip bitmap.
pointer Pointer Este utilizat pentru selectarea, mutarea sau redimensionarea
unui control.
buton radio RadioButton Este folosit pentru ca utilizatorul s selecteze un singur
element dint-un grup de selec ii.
caset de text TextBox Este utilizat pentru afi area textului generat de o aplica ie
sau pentru a primi datele introduse de la tastatur de c tre
utilizator.

II.5. Aplica ii

II.5.1. Numere pare


Acest exemplu afi eaz numerele pare din intervalul [0,n) unde n este o variabil global a
c rei valoare este introdus de la tastatur . Se deschide o aplica ie Windows Forms pe care o ve i
denumi Numere pare. Din fereastra Properties modifica i numele formularului. 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 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:

private void button1_Click(object sender, EventArgs e)


{
n = Convert.ToInt32(textBox1.Text);
for (;i<n;i=i+2)
{
textBox2.Text = textBox2.Text + " " + Convert.ToString(i);
}
}

În fereastra Solution Explorer executa i dublu clic pe Form1.Designer.cs pentru a declara


variabilele globale n i i, în zona de declara ii a func iei InitializeComponent().

private System.Windows.Forms.Label label1;


private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Button button1;
int i=0,n;

Î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 Multiline schimb setarea implicit a controlului TextBox de la o singur linie, la


mai multe linii. Pentru a realiza acest lucru trage i un TextBox într-un formular i modifica i
valoarea propriet ii Multiline din panoul Properties de la False la true.

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 Font determin fontul folosit într-un formular sau control.

Proprietatea ImageAlign specific alinierea unei imagini a ezate pe suprafa a controlului.

Proprietatea TabIndex seteaz sau returneaz pozi ia controlului în cadrul aranj rii taburilor.

Proprietatea Visible seteaz vizibilitatea controlului.

Proprietatea Width and Height permite setarea în l imii i a l imii controlului.

II.5.3. Metode i evenimente


Un eveniment este un mesaj trimis de un obiect atunci când are loc o anumit ac iune.
Aceast actiune poate fi: interac iunea cu utilizatorul (mouse click) sau interac iunea cu alte entit i
de program. Un eveniment (event) poate fi ap sarea unui buton, o selec ie de meniu, trecerea unui
anumit interval de timp, pe scurt, orice ce se intampl în sistem i trebuie s primeasc un raspuns
din partea programului. Evenimentele sunt propriet i ale clasei care le public . Cuvantul-cheie
event contoleaz cum sunt accesate aceste propriet i.

Metodele Show() i Close(). Evenimentul Click

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

Exemplul 2: Deschidere i închidere de formulare

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

private void button1_Click(object sender, EventArgs e)


{
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:

private void button1_Click(object sender, EventArgs e) {


Form2 form2 = new Form2();form2.Show();
}

Î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:

private void button2_Click(object sender, EventArgs e) {


pictureBox1.Image = Image.FromFile("C:\\Imagini\\rat.gif");
pictureBox1.Visible = true;
}

Ve i ob ine la rularea aplica iei afi area uneia din cele dou imagini, în func ie de butonul ap sat.

sau

Exemplul 4: Caset de text

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.

private void button1_Click(object sender, EventArgs e)


{string a = "PLATFORMA .NET";textBox1.Text = a;}

În acest moment rula i programul ap sând tasta F5 i face i clic pe buton.

152
Exemplul 5: Caset de mesaj

Pentru a crea o caset mesaj, apel m metoda MessageBox.Show();.Într-o nou aplica ie


Windows Forms, trage i un control de tip Button în formular, modifica i textul butonului cum dori i
sau ca în imaginea al turat „va apare un mesaj”, executa i dublu clic pe buton i ad uga i în
administratorul evenimentului Clic linia de program: MessageBox.Show("ti-am spus");. Apoi
rula i aplica ia.

Exemplul 6:

Este un exemplu de utilizare a controalelor de selec ie CheckBox i RadioButton.


Propietatea Checked indic dac am selectat controlul. Dac proprietatea ThreeState este
setat , atunci se schimb func ionalitatea acestor controale, în sensul c acestea vor permite
setarea unei alte st ri. În acest caz, trebuie verificat propietatea CheckState(Checked,
Unchecked, Indeterminate) pentru a vedea starea controlului CheckBox.

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:

private void radioButton1_Click(object sender, System.EventArgs e){


if (checkBox1.CheckState==CheckState.Checked &&
checkBox2.CheckState==CheckState.Checked &&
checkBox3.CheckState==CheckState.Checked &&
checkBox5.CheckState==CheckState.Checked &&
checkBox4.CheckState==CheckState.Unchecked)
MessageBox.Show("CORECT");
else MessageBox.Show("Indicatie> Daca punem un sac in altul....");
label2.Visible=false;
radioButton1.Checked=false; radioButton2.Checked=false;
radioButton1.Visible=false; radioButton2.Visible=false;}
private void button1_Click(object sender, System.EventArgs e)
{label2.Visible=true;radioButton1.Visible=true;radioButton2.Visible=true;
}

Exemplul 7: Construc ia Fractalului

Se deschide o aplica ie Windows Forms pe care o ve i denumi Fractal. Stabili i dimensiunea


formularului la 740 cu 540, stabili i culoarea de fond a formularului alegând una dintre cele
predefinite din op iunea BackColor.
Cu ajutorul metodei Drag and drop plasa i pe formular: dou controale de tip Label în care
ve i introduce urm toarele texte „Construirea unui fractal” (pentru eticheta pozi ionat în partea de
sus a formularului) i „Introduce i num rul de p trate” (pentru cea de a doua etichet pe care e
bine s o pozi iona i la o distan nu prea mare de prima), plasa i pe formular i un control de tip
TextBox, un control de tip Button, i un control de tip Timer pentru care seta i intervalul la 50.

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.

private void button1_Click(object sender, EventArgs e)


{
m = 1;
timer1.Start();
}

În aceea i fereastr de cod scriem func ia recursiv patrat care va genera fractalul.

void patrat(int n, int x, int y, int l)


{
int l2 = l / 2;
int l4 = l / 4;
int l3 = l2 + l4;

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.

private void timer1_Tick(object sender, EventArgs e)


{
if (m <= Convert.ToInt32(textBox1.Text))
{
int x = 300, y = 300, l = 150;
patrat(m, x, y, l);
m = m + 1;
}
}

În fereastra Solution Explorer executa i dublu clic pe Form1.Designer.cs pentru a declara


variabila global m, în zona de declara ii a func iei InitializeComponent().

private System.Windows.Forms.Label label1;


private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Timer timer1;
int m;

În acest moment aplica ia este gata. Din meniul File alege i op iunea Save All i rula i
aplica ia.

Metodele ShowDialog() i Clear(). Evenimentul MouseEnter.

Exemplul 8: Casete de dialog

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.

private void button1_MouseEnter(object sender, EventArgs e)


{ Form2 w = new Form2(); w.ShowDialog(); }

Intra i în codul surs pentru Form1.Designer.cs i modifica i linia de program:

this.button1.Click += new System.EventHandler(this.button1_Click);

astfel:

this.button1.MouseEnter += new System.EventHandler(this.button1_MouseEnter);

Acest eveniment al controlului Button v permite ca la o simpl plimbare pe buton f r a


executa clic pe el, s se execute codul surs al metodei.

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:

private void button1_Click(object sender, EventArgs e)


{textBoxText = textBox1.Text;this.Close();}

Executa i dublu clic pe butonul Cancel i folosi i urm torul cod pentru administratorul
evenimentului Clic:

private void button2_Click(object sender, EventArgs e)


{Form2 v = new Form2(); v.ShowDialog();
if (v.DialogResult != DialogResult.OK){ this.textBox1.Clear(); }}

157
La începutul clasei Form2 ad uga i declara ia: public string textBoxText; iar la
sf r itul clasei Form2 ad uga i proprietatea:

public string TextBoxText


{get{ return(textBoxText);}

Acum pute i rula acest program.

Metoda Start(). Evenimentul MouseLeave.

Exemplul 9: Schimb culoarea

Î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:

private void button1_MouseLeave(object sender, EventArgs e)


{timer1.Start();}

Intra i în codul surs pentru Form1.Designer.cs i modifica i linia de program:

this.button1.Click += new System.EventHandler(this.button1_Click);

astfel:

this.button1.MouseLeave += new System.EventHandler(this.button1_MouseLeave);

Evenimentul MouseLeave va permite executarea codului surs a metodei în momentul în


care ve i plimba mouse-ul pe deasupra imaginii butonului i nu la executarea clic-ului.

Executa i dublu clic pe butonul STOP i insera i linia de cod timer1.Stop();

Declara i urm toarea variabil ca fiind variabil local pentru clasa Form1

Random r = new Random(200);

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:

private void timer1_Tick(object sender, EventArgs e)


{label1.BackColor = Color.FromArgb(r.Next(255), r.Next(255),
r.Next(255));}

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

private void button1_Click(object sender, System.EventArgs e) {


if (button1.BackColor== Color.IndianRed) button1.BackColor=Color.Yellow;
else button1.BackColor= Color.IndianRed;}
private void button4_MouseEnter(object sender, System.EventArgs e)
{button4.BackColor=Color.YellowGreen;button4.Text="Butoane apasate";}
private void button4_MouseLeave(object sender, System.EventArgs e)
{textBox1.Visible=false;button4.Text="Starea butoanelor";
button4.BackColor=Color.Orange;}
private void button4_Click(object sender, System.EventArgs e)
{textBox1.Visible=true;textBox1.Text="";
if(
button1.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'A';
if(
button2.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'B';
if(
button3.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'C';
}

160
i

Exemplul 11: Hyperlink

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" );}

Exemplul 12: Curba Beziers

Se deschide o aplica ie Windows Forms pe care o ve i denumi Culori. Din fereastra


Properties modifica i numele formularului redenumindu-l. 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 Timer iar din caseta Properties intervalul îl seta i la 50.
Executa i dublu clic pe suprafa a formularului i completa i clasa Form1 cu declararea
variabilelor locale conform modelului de mai jos:

Random r = new Random();


PointF[] v = new PointF[4];
Graphics graf;

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++;
}

Executa i dublu clic pe butonul START i completa i func ia button1_Click conform


modelului de mai jos:

private void button1_Click(object sender, EventArgs e)


{graf = this.CreateGraphics();
timer1.Start();
}

În fereastra Solution Explorer executa i dublu clic pe Form1.Designer.cs pentru a declara


variabilele globale i,cx,cy în zona de declara ii a func iei InitializeComponent().

private System.Windows.Forms.Button button1;


private System.Windows.Forms.Timer timer1;
int i = 0, cx = 300, cy = 300;

Î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:

private void button1_Click(object sender, System.EventArgs e)


{ MessageBox.Show(textBox1.Text);
}
private void button2_Click(object sender, System.EventArgs e)
{ Form1.ActiveForm.Dispose();
}

Metodele Clear() i Add()


Exemplul 14:

Controale pentru listare (ListBox, CheckedListBox, ComboBox, ImageList) ce pot fi


legate de un DataSet, de un ArrayList sau de orice tablou (orice surs de date ce implementeaz
interfa a IEnumerable).

În acest exemplu elementele selectate din CheckedListBox se adaug în ListBox. Dup


ad ugarea pe formular a CheckedListBox-ului, stabilim colec ia de itemi (Properties-Items-
Collection), butonul Selec ie i ListBox-ul.
Evenimentul Click asociat butonului Selectie gole te mai întâi listBox-ul
(listBox1.Items.Clear();) i dup aceea adaug în ordine fiecare element selectat din
CheckedListBox. Suplimentar se afi eaz o etichet cu itemii selecta i.

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

private void btnDeseneaza_Click(object sender, EventArgs e)


{
Graphics graphic = this.CreateGraphics();
for (int i=0; i < imageList1.Images.Count;i++)
{
imageList1.Draw(graphic, i * 120, 60, i);
}
graphic.Dispose();
}

În urma rul rii aplica iei ve i ob ine:

167
Evenimentul DateSelected

Exemplul 17: MonthCalendar

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.

Exist 2 evenimente pe care controlul le expune: DateSelected i DateChanged. În rutinele


de tratare a acestor evenimente, programatorul are acces la un obiect de tipul
DateRangeEventArgs care con ine propriet ile Start i End (reprezentând intervalul de timp
selectat).

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:

private void monthCalendar1_DateSelected(object sender,


System.Windows.Forms.DateRangeEventArgs e)
{ this.label1.Text = "Interval selectat: Start = "
+e.Start.ToShortDateString() + " : End = "+ e.End.ToShortDateString();
if (e.Start.ToShortDateString()==e.End.ToShortDateString())
{String x=e.Start.ToShortDateString();
if(!(comboBox1.Items.Contains(x)))comboBox1.Items.Add(e.End.ToShortDateString
());}
}

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

Exemplul 18: Modificare propriet i

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

FontDialog fd = new FontDialog();


fd.ShowColor = true;
fd.Color = Color.IndianRed;
fd.ShowApply = true;
fd.Apply += new EventHandler(ApplyFont);
if(fd.ShowDialog() != System.Windows.Forms.DialogResult.Cancel)
{ this.richTextBox1.Font= fd.Font;
this.richTextBox1.ForeColor=fd.Color;
}
ColorDialog cd = new ColorDialog();
cd.AllowFullOpen = true;
cd.Color = Color.DarkBlue;
if(cd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
this.richTextBox1.ForeColor = cd.Color;

Mutarea toolbar-ul este dirijat de evenimentele produse atunci când ap s m butonul de


mouse i/sau ne deplas m pe suprafa a ferestrei.

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;}

private void toolBar1_MouseUp(object sender, MouseEventArgs e)


{ am_apasat = false;toolBar1.Capture = false;}

private void toolBar1_MouseMove(object sender, MouseEventArgs e)


{ if (am_apasat)
{ if(toolBar1.Dock == DockStyle.Top || toolBar1.Dock == DockStyle.Left)
{ // daca depaseste atunci duc in stanga sus
if (forma_deplasata.X < (e.X-20) || forma_deplasata.Y < (e.Y-20))
{ am_apasat = false;// Disconect toolbar
toolBar1.Dock = DockStyle.None;toolBar1.Location = new Point(10, 10);
toolBar1.Size = new Size(200, 45);
toolBar1.BorderStyle = BorderStyle.FixedSingle;
}
}
else if (toolBar1.Dock == DockStyle.None)
{toolBar1.Left = e.X + toolBar1.Left - forma_deplasata.X;
toolBar1.Top = e.Y + toolBar1.Top - forma_deplasata.Y;
if (toolBar1.Top < 5 || toolBar1.Top>this.Size.Height-20)
{ am_apasat = false;toolBar1.Dock = DockStyle.Top;
toolBar1.BorderStyle = BorderStyle.Fixed3D;}
else if (toolBar1.Left < 5 || toolBar1.Left > this.Size.Width - 20)
{ am_apasat = false;toolBar1.Dock = DockStyle.Left;
toolBar1.BorderStyle = BorderStyle.Fixed3D;
}}}}

Metoda ShowDialog()

Exemplul 18: Fi iere

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.

OpenFileDialog of = new OpenFileDialog();


of.Filter = "Text Files (*.txt)|*.txt";
of.Title = "Fisiere Text";
if (of.ShowDialog() == DialogResult.Cancel)return;
richTextBox1.Text="";
richTextBox1.Visible=true;
FileStream strm;
try{strm = new FileStream (of.FileName, FileMode.Open, FileAccess.Read);
StreamReader rdr = new StreamReader (strm);
while (rdr.Peek() >= 0)
{string str = rdr.ReadLine ();
richTextBox1.Text=richTextBox1.Text+" "+str;
}}
catch (Exception)
{MessageBox.Show ("Error opening file", "File Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);}

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 myPoint = new Point(1, 2);

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

Putem construi un obiect de tip Point pentru a redimensiona un alt obiect.

Size mySize = new Size(15, 100);


Point myPoint = new Point(mySize);
Console.WriteLine("X: " + myPoint.X + ", Y: " + myPoint.Y);

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.

Color myColor = Color.Brown; button1.BackColor = myColor;

Substructura FromArgb a structurii Color returneaz o culoare pe baza celor trei


componente ale oric rei culori (red, green, blue).

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

Exemplul 19: Desen

Aplica ia este un exerci iu care deseneaz cercuri de raze i culori aleatoare i emite
sunete cu frecven aleatoare.

Random x = new Random();


Console.Beep(300 + x.Next(1000), 150);
Graphics g = this.CreateGraphics();
int i = 1 + x.Next(30);
Pen p = new Pen(Color.FromArgb(x.Next(256), x.Next(256), x.Next(256)));
g.DrawEllipse(p, x.Next(100), x.Next(100), i, i);
Thread.Sleep(200);

Exemplul 19: Pictogram

În exemplul urm tor se construie te o pictogram pe baza unei imagini.

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.

II.5.5.(1) Validarea la nivel de câmp

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

private void textBox1_KeyUp(object sender,


System.Windows.Forms.KeeyEventArgs e)
{if(e.Alt==true) MessageBox.Show ("Tasta Alt e apasata"); // sau
if(Char.IsDigit(e.KeyChar)==true) MessageBox.Show("Ati apasat o cifra");
}

II.5.5.(2) Validarea la nivel de utilizator

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

myErrorProvider.SetError(txtName," Numele nu are spatii in stanga");

II.5.6. MessageBox

Ne propunem ca în cele ce urmeaz s realiz m o aplica ie simpl , în care vom folosi


câteva controale i vom explica ceea ce se întâmpl din punct de vedere al program rii orientate
obiect.

Ne propunem s construim o fereastr cu un buton, pe care, dac -l ap s m, s


deschid o alt fereastr cu un mesaj: “BUNA ZIUA!”

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!");

Pentru a compila i executa ap s m F5. Ob inem:

175
S analiz m pu in codul nostru, aducându-ne aminte de no iunile de programare orientat
obiect studiate:

MessageBox este o clas din spa iul de nume System.Windows.Forms, derivat


din clasa Object
Show este o metod static din clasa MessageBox

Î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:

MessageBox.Show("BUNA ZIUA!", "Salut");

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

MessageBox.Show("BUNA ZIUA!", "Salut", MessageBoxButtons.YesNo);

S mai încerc m o alt form supradefinit a metodei Show, folosind patru


parametri: al patrulea se va referi la icoana care s apar , al turi de textul “BUNA ZIUA”. Avem la
dispozi ie 9 icoane.

MessageBox.Show("BUNA ZIUA!", "Salut", MessageBoxButtons.YesNo,


MessageBoxIcon.Asterisk);

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.

Desen m o figur geometric care va constitui viitoarea noastr fereastr . Presupunem c


dorim ca fereastra s aib forma de oval.

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

Salv m desenul cu extensia gif: oval.gif

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

Deformez PictureBox-ul astfel încât ovalul desenat s ocupe o suprafa care s


corespund esteticii programatorului

180
Selectez Form1, iar la propriet ile corespunz toare voi selecta:

BackColor 255;255;0 – în acest moment fundalul ferestrei coincide ca i culoare cu


fundalul desenului nostru
TransparencyKey 255;255;0 - (acelea i valori ca i la culoarea fundalului)

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

D m clic pe PictureBox, ne ducem la Fereastra Properties i select m evenimentele


legate de acest control. D m dublu clic pe evenimentul MouseDown i scriem în Fereastra
Form1.cs codul corespunz tor butonului stânga al mouse-ului, cod ce se refer la posibilitatea de
a putea prinde i deplasa interfa a noastr :

if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
}

Mai includem în sursa noastr i:

183
using System.Runtime.InteropServices;

În final codul arat :

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();
}

private void button1_Click(object sender, EventArgs e)


{
this.Close();
}

private void pictureBox1_MouseDown(object sender,


MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
}
}
}
}

Revenim în fereastra Form1.cs[Designer], select m Form1, iar la Properties alegem:

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

O aplica ie interesant const în a ne crea propriul browser.

În Visual C# alegem: File | New Project | Windows Forms Application, iar ca nume
BrowserUtilizator.

În Form1, în Fereastra Properties, la Text scriem B R O W S E R, cuvânt care va apare pe


bara de titlu. În aceast fereastr aducem:
TextBox la care, la TextBox Tasks bif m MultiLine

Button la care-i schimb m Text-ul în GO


WebBrowser pe care îl aliniem dup laturile din stânga, dreapta i jos a ferestrei.

D m dublu clic pe butonul GO i scriem codul necesar navig rii:

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 .

Vom încerca alt metod .

De la grupul de controale Container aleg SplitContainer. De la op iunea Split Container


Task aleg Horizontal splitter orientation

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 .

În Panoul 1 vom plasa TextBox-ul i Button-ul, iar în Panoul 2 WebBrowser-ul.


Pentru WebBrowser aleg proprietatea Doc in parent container, moment în care
WebBrowser-ul se va lipi (va adera) de marginile marginile Panoului 2

D m dublu clic pe butonul GO i scriem acela i cod ca mai înainte.

Rul m programul i observ m c dac maximiz m fereastra WebBrowser-ul r mâne lipit


de marginile ferestrei.

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.

Select m TextBox-ul. dup care din fereastra Properties d m clic în c su a


corespunz toare propriet ii Anchor. Suntem asista i grafic pentru a stabili partea în care dorim
ca TextBox-ul s fie lipit de margini.

189
Alegem Stânga, Dreapta i Sus dând clic pe segmentele corespunz toare.

La fel proced m pentru butonul GO, unde alegem Sus i Dreapta

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:

pentru navigarea înapoi în lista de adrese

pentru navigarea înainte în lista de adrese

pentru pagina de start

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

O alt metod pentru deformarea propor ional a WebBrowser-ului, împreun cu ferestra


aplica iei, o putem realiza doar folosind proprietatea Anchor pentru toate elementele din fereastr .

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:

Proprietate Valoare Explica ie


(Name) aplCeas

Enabled True Activarea controlului de timp


Interval 1.000 Num rul de milisecunde dintre apelurile la metoda
de tratare a evenimentului. Se stabileste, în cazul
de fa num r toarea din secund în secund

Aducem în formular un control Label cu urm toarele propriet i:

Control Proprietate Valoare


label1 (Name) labelCeas
AutoSize False
BorderStyle Fixed3D
FontSize 16,25, Bold
Location 82;112
192
Text
Size 129;42
TextAlign MiddleCenter

D m clic pe icoana de la timer care are


numele aplCeas, iar la Events, la Tick select m
aplCeas_Tick

D m dublu clic pe aplCeas_Tick i inser m


codul:

private void lblCeas_Tick(object sender, EventArgs e)


{
DateTime OraCurenta = DateTime.Now;
lblCeas.Text=OraCurenta.ToLongTimeString();
}

Compil m i ob inem într-o fereastr


vizualizarea orei sistemului

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.

Defini i coloanele tabelului prin stabilirea componentelor:


numele coloanei – acesta trebuie s fie unic în cadrul tabelei
tipul de date – tipul de date trebuie s fie un tip de date valid, din acest motiv este bine s
utiliza i unul dintre tipurile de date ce v apar în lista derulant

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.

II.6.2. Popularea bazei de date


Pentru a introduce date în tabel chiar de la crearea ei executa i clic dreapta pe butonul
mouse-ului dup selectarea fi ierului i alege i op iunea Open Table.

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.

II.6.3. Introducere în limbajul SQL

II.6.3.(1) Introducere ANSI SQL

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

Forma instruc iunii SELECT con ine dou clauze:


SELECT[DISTINCT] specific lista coloanelor ce urmeaz s fie returnate în setul de rezultate.
Pentru a selecta toate coloanele se poate folosi simbolul asterisc *. Cuvântul cheie DISTINCT
ad ugat dup cuvântul cheie SELECT elimin rândurile duplicat din rezultatele înregistr rii.
FROM specific lista tabelelor sau vizualiz rilor de unde select m date.
SELECT [ID]
,[NUME]
FROM [elev].[dbo].[T1]

Exemplul 1: am cerut s vizualizez înregistrarile din coloanele ID i NUME ale tabelului Elev
din baza de date CLASA.

Exemplul 2: procesarea mai multor comenzi cu SQLCMD

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

Exemplul2: de utilizare a instruc iunii INSERT cu includerea listei de coloane. Pentru a


vizualiza modificarea folosi i instruc iunea SELECT.

INSERT INTO [elev].[dbo].[T1]


([ID]
,[NUME])
VALUES
(<ID, numeric,>
,<NUME, nvarchar(50),>)

pentru a insera rânduri multiple într-un tabel se folose te o instruc iune SELECT intern

Exemplul 3: în acest exemplu instruc iunea SELECT va g si valoarea maxim de pe coloana


ID, va incrementa aceast valoare cu o unitate, ob inând astfel cheia primar a unei noi
înregistr ri, înregistrare care va primi pe coloana NUME valoarea POPESCU. Pentru a vizualiza
modificarea folosi i instruc iunea SELECT.

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,,>

Exemplul 4: presupunem c am gre it ID-ul elevului POPESCU în loc de 7 ar fi trebuit s


introducem 21. Cu ajutorul instruc iunii Update vom modifica acest ID. Pentru a vizualiza
modificarea folosi i instruc iunea SELECT.

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 .

II.6.3.(6) Comenzi de manipulare tabele

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

Exemplul 6: dorim s ad ug m o coloan la un tabel creat anterior.


alter table nume_tabel
add <definitie coloana>
unde <definitie coloana>=nume_tabel tip_de_date

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

jos iar apoi executa i clic pe mouse pe butonul

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.

II.6.3.(7) Manipularea datelor

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.

Func ia Max – returneaz cea mai mare valoare înregistrat pe o coloan


Sintaxa: SELECT MAX(column_name) FROM table_name

Exemplul 10: cerem s se afi eze cel mai mare salariu din tabela Salarii.

Func ia Min – returneaz cea mai mic valoare înregistrat pe o coloan


Sintaxa: SELECT MIN(column_name) FROM table_name

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.

II.7. Accesarea i prelucrarea datelor cu ajutorul mediului vizual


Mediul de dezvoltare Visual Studio dispune de instrumente puternice i sugestive pentru
utilizarea bazelor de date în aplica ii. Conceptual, în spatele unei ferestre în care lucr m cu date
preluate dintr-una sau mai multe tabele ale unei baze de date se afl obiectele din categoriile
Connection, Command, DataAdapter i DataSet prezentate. „La vedere” se afl controale de tip
DataGridView, sau TableGridView, BindingNavigator etc.
Meniul Data i fereastra auxiliar Data Sources ne sunt foarte utile în lucrul cu surse de
date externe.

II.7.1. Conectare i deconectare.


Dup crearea unei baze de date în SQL informa iile înregistrate în tabela sau tabelele bazei
de date pot fi utilizate într-o aplica ie din Visual C# într-un formular sau într-o aplica ie consol .
Vom prezenta acum modul în care se poate utiliza o baz de date într-un formular creat în
Windows Forms. Pentru a realiza acest lucru dup deschiderea aplica iei din fereastra Toolbox
trage i pe formular cu ajutorul procedeului drag-and-drop o DataGridView, conform exemplului de
mai jos.

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.

II.7.2. Opera ii specifice prelucr rii tabelelor

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

confirmarea introducerii noii înregistr ri o ve i ob ine imediat

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.

II.8. Accesarea i prelucrarea datelor cu ajutorul ADO.NET

ADO.NET (ActiveX Data Objects) reprezint o parte component a nucleului .NET


Framework ce permite conectarea la surse de date diverse, extragerea, manipularea i
actualizarea datelor.

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.

II.8.1. Arhitectura ADO.NET


Componentele principale ale ADO.NET sunt DataSet i Data Provider. Ele au fost proiectate
pentru accesarea i manipularea datelor.

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 :

Exemplul 2: conexiunea se face introducând explicit numele serverului ca în exemplul de mai


jos
SqlConnection con = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial
Catalog=SALARII;IntegratedSecurity=SSPI");
Sau implicit :

211
SqlConnection co = new SqlConnection(".\\SQLEXPRESS;Initial
Catalog=SALARII;IntegratedSecurity=SSPI");

ConnectionString (String, cu accesori de tip get i set ) define te un ir care permite


identificarea tipului i sursei de date la care se face conectarea i eventual contul i parola de
acces. Con ine lista de parametri necesari conect rii sub forma parametru=valoare, separa i prin ;.
Parametru Descriere
Specific furnizorul de date pentru conectarea la sursa de date. Acest furnizor
Provider trebuie precizat doar dac se folose te OLE DB .NET Data Provider, i nu se
specific pentru conectare la SQL Server.
Data Source Identific serverul, care poate fi local, un domeniu sau o adresa IP.
Initial specific numele bazei de date. Baza de date trebuie s se g seasc pe serverul
Catalog dat în Data Source
Integrated
Logarea se face cu user-ul configurat pentru Windows.
Security
User ID Numele unui user care are acces de logare pe server
Password Parola corespunz toare ID-ului specificat.

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:

SqlConnection con = new SqlConnection(".\\SQLEXPRESS;Initial


Catalog=SALARII; Connect Timeout=30;IntegratedSecurity=SSPI");

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

SqlCommand cmd = new SqlCommand();

SqlCommand(string CommandText, SqlConnection con )

SqlCommand cmd = new SqlCommand("DELETE FROM SALAR_ANGAJAT WHERE nume


= ’PREDA’",co);

Cancel() opre te o comand aflat în executare.


Dispose() distruge obiectul comand .
ExecuteNonQuery() execut o comand care nu returneaz un set de date din baza de date.
În cazul în care comanda a fost de tip INSERT, UPDATE, DELETE, se returneaz num rul de
înregistr ri afectate.

Exemplul 4: se va terge înregistrarea cu numele PREDA i se va returna un obiect afectat

SqlConnection co = new SqlConnection("DATA SOURCE=DANA-


D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand cmd = new SqlCommand("DELETE FROM
SALAR_ANGAJAT WHERE nume = ’PREDA’",co);
cmd.ExecuteNonQuery();
Console.ReadLine();
co.Close();

ExecuteReader() execut comanda i returneaz un obiect de tip DataReader.

Exemplul 5: Se ob ine con inutul tabelei într-un obiect de tip SqlDataReader.

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 reader = cmd.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();

215
Exemplul 6: Am construit o nou tabel tot în baza de date salarii numit telefoane. Con inutul
ei este prezentat mai jos.

De data aceasta vom afi a con inutul ambelor tabele.


SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
SqlCommand cmd = new SqlCommand("select * from
salar_angajat;select * from telefoane", co);
co.Open();SqlDataReader reader = cmd.ExecuteReader();
Console.WriteLine("Datele din tabela SALARII");
Console.WriteLine(" ID NUME PRENUME VECHIME");
Console.WriteLine();
do
{ while (reader.Read())
{
Console.WriteLine(String.Format("\t{0}\t{1}\t{2} \t {3} ",
reader[0], reader[1], reader[2], reader[3]));
}
Console.WriteLine("Datele din tabela TELEFOANE");
Console.WriteLine();
Console.WriteLine(" ID NUME PRENUME TELEFON");
Console.WriteLine();
} while (reader.NextResult());
Console.WriteLine();
Console.ReadLine();

Metoda ExecuteReader() mai are un argument op ional de tip enumerare,


CommandBehavior, care descrie rezultatele i efectul asupra bazei de date:
- CloseConnection (conexiunea este închis atunci când obiectul DataReader este închis),
- KeyInfo (returnez informa ie despre coloane i cheia primar ),
- SchemaOnly (returnez doar informa ie despre coloane),

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();

ExecuteScalar() execut comanda i returneaz valoarea primei coloane de pe primul rând a


setului de date rezultat. Este folosit pentru ob inerea unor rezultate statistice.

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();

II.8.7. Interogarea datelor

Pentru extragerea datelor cu ajutorul unui obiect SqlCommand trebuie s utiliz m metoda
ExecuteReader care returneaz un obiect SqlDataReader.

// Instan iem o comand cu o cerere i preciz m conexiunea


SqlCommand cmd = new SqlCommand("select salar from salar_angajat", co);
// Ob inem rezultatul cererii
SqlDataReader rdr = cmd.ExecuteReader();

II.8.8. Inserarea datelor


Pentru a insera date într-o baz de date utiliz m metoda ExecuteNonQuery a obiectului
SqlCommand .
// irul care p streaz comanda de inserare
string insertString = @"insert into salar_angajat(ID,NUME,PRENUME,VECHIME,SALAR)
values (6 ,'BARBU' ,'EUGENIU', 17,1993)";
// Instan iem o comand cu acest cerere i preciz m conexiunea
SqlCommand cmd = new SqlCommand(insertString, co);
// Apel m metoda ExecuteNonQuery pentru a executa comanda
cmd.ExecuteNonQuery();

218
Exemplul 9: vom insera în tabela salar_angajat o nou înregistrare i vom afi a tot con inutul
tabelei

SqlConnection co = new SqlConnection("DATA SOURCE=DANA-


D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
try
{co.Open();
string insertString = @"insert into salar_angajat(ID ,NUME ,PRENUME
,VECHIME ,SALAR)values (6,'BARBU','EUGENIU',17,1993)";
SqlCommand cmd = new SqlCommand(insertString, co);
cmd.ExecuteNonQuery();}
finally
{if (co != null) { co.Close(); }}
SqlCommand comand = new SqlCommand("SELECT * FROM SALAR_ANGAJAT", co);
co.Open();
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(); }

II.8.9. Actualizarea datelor

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

SqlConnection co = new SqlConnection("DATA SOURCE=DANA-


D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
// irul care p streaz comanda de tergere
string deleteString = @"delete from SALAR_ANGAJAT where NUME
= 'BIBIRE'";
// Instan iem o comand
SqlCommand cmd = new SqlCommand();
// Set m proprietatea CommandText
cmd.CommandText = deleteString;
// Set m proprietatea Connection
cmd.Connection = co;
// . Execut m comanda
cmd.ExecuteNonQuery();
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(); }

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(); } }}

func ia care actualizeaz anumite valori specificate


public void UpdateData()
{
try
{
conn.Open();
string updateString = @"update SALAR_ANGAJAT set PRENUME =
'MARIA'
where PRENUME = 'DANIELA'";
SqlCommand cmd = new SqlCommand(updateString);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
finally
{
if (conn != null) { conn.Close(); }
}
}
func ia care terge una sau mai multe înregistr ri în func ie de condi ia impus
public void DeleteData()
{
try
{
conn.Open();
string deleteString = @"delete from SALAR_ANGAJAT where NUME
= 'BARBU'";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = deleteString;
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
finally
{ if (conn != null) { conn.Close(); } }
}
func ia care num r înregistr rile din tabel
public int GetNumberOfRecords()
{
int count = -1;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("select count(*) from
SALAR_ANGAJAT", conn);
count = (int)cmd.ExecuteScalar();
}
finally
{
if (conn != null) { conn.Close(); }
}
return count;
}

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:

Add - implicit, DataAdapter adaug coloana la schema tablei

AddWithKey – se adaug coloana i informa ii relativ la cheia primar

Ignore - se ignor lipsa coloanei respective, ceea ce duce la pierdere de date

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.

SqlCommandBuilder cmdBldr = new SqlCommandBuilder (daSALAR);

La ini ializarea unui CommandBuilder se apeleaz un constructor care prime te ca


parametru un adapter, pentru care vor fi construite comenzile. SqlCommandBuilder are nu poate
construi decât comenzi simple i care se aplica unui singur tabel. Atunci când trebui ca sa facem
comenzi care vor folosi mai multe tabele este recomandata construirea separat a comenzilor i
apoi ata area lor adapterului folosind propriet i.

Popularea DataSet-ului se face dup ce am construit cele dou instan e:

daSALAR.Fill (dsNUME, "NUME");

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

DataGrid dgANGAJAT = new DataGrid();


dgANGAJAT.DataSource = dsNUME;
dgANGAJAT.DataMembers = "NUME";

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.

daSALAR.Update (dsNUME, "NUME");

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.

Noi ne-am propus s cre m o aplica ie care s :

- insereze una sau mai multe înregistr ri,

-s tearg una sau mai multe înregistr ri,

- s afi eze permanent num rul de astfel de modific ri efectuate,

- s afi eze con inutul tabelei dup fiecare modificare,

- s calculeze suma salariilor din tabel

- s afi eze cel mai mare salar

- s afi eze cea mai mic vechime

- s afi eze înregistr rile în ordine lexicografic

Pentru a realiza i voi acela i lucru va trebui s parcurge i pa ii explica i în continuare.

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.

public partial class Form1 : Form


{
int nrmodificari = 0; SqlConnection co;
public Form1()
{
InitializeComponent();
226
co = new SqlConnection(@"Data Source=DANA-
D90FDEF1A8\SQLEXPRESS;Database=dana;Trusted_Connection=yes;");
co.Open();
}
Executa i ciclk dublu pe butonul INSERARE i completa i sursa lui cu instruc iunile care
vor permite inserarea unor înregistr ri noi în tabel . Num rul de inser ri îl ve i putea vizualiza în
caseta de text asociat etichetei cu numele „NUM R DE MODIFIC RI”.
private void button1_Click(object sender, EventArgs e)
{
string insertsql;
insertsql="insert into salar_angajat (id,nume,prenume,vechime,salar) values
('";insertsql+=textBox1.Text+"','"+textBox2.Text+"','"+textBox3.Text+"','"+textB
ox4.Text+"','"+textBox5.Text+"')";
SqlCommand cmd = new SqlCommand(insertsql, co);
nrmodificari = nrmodificari+cmd.ExecuteNonQuery();
textBox6.Text =Convert.ToString(nrmodificari);}
}

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.

Executa i clic dublu pe butonul STERGE i completa i sursa cu codul care v va


permite tergerea unui angajat al c rui nume va fi preluat din caseta de text.
private void button3_Click(object sender, EventArgs e)
{
string deletesql;
deletesql = "delete from salar_angajat where nume='"; deletesql += textBox7.Text+ "'";
SqlCommand cmd = new SqlCommand(deletesql, co);
nrmodificari = nrmodificari + cmd.ExecuteNonQuery();
textBox6.Text = Convert.ToString(nrmodificari);
}
Pentru a ob ine suma salariilor din tabel va trebui s completa i formularul în mod
design cu înc un buton cel pe care noi l+am numit SUMA SALARII, în dreptul lui s ad uga i o

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:

private void button5_Click(object sender, EventArgs e)


{
int min;
SqlCommand cmd = new SqlCommand("select min(vechime) FROM SALAR_ANGAJAT", co);
min = (int)cmd.ExecuteScalar();
textBox9.Text = Convert.ToString(min);
}

private void button6_Click(object sender, EventArgs e)


{
int max;
SqlCommand cmd = new SqlCommand("select max(SALAR) FROM SALAR_ANGAJAT", co);
max = (int)cmd.ExecuteScalar();
textBox10.Text = Convert.ToString(max);
}

În dreptul butonului AFISARE ad uga i un buton pe care ve i insera textul: AFISARE IN


ORDINE LEXICOGRAFICA, i completa i sursa lui cu urm torul cod.
private void button1_Clic_1(object sender, EventArgs e)
{
string selectSQL = "select * FROM SALAR_ANGAJAT ORDER BY NUME ASC";
SqlCommand cmmd = new SqlCommand(selectSQL, co);
SqlDataAdapter adapter = new SqlDataAdapter(cmmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "salar_angajat");
label7.Text = ""; label8.Text = ""; label9.Text = ""; label10.Text = "";
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";

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

S-ar putea să vă placă și