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 aplicaiilor 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. Instruciunile try-catch-finally i throw............................................................................................ 48
I.3. PRINCIPIILE PROGRAMRII ORIENTATE PE OBIECTE ................................................................................. 75
I.3.1. Evoluia tehnicilor de programare ................................................................................................ 75
I.3.2. Tipuri de date obiectuale. ncapsulare .......................................................................................... 76
I.3.3. Suprancrcare .............................................................................................................................. 78
I.3.4. Motenire ....................................................................................................................................... 79
I.3.5. Polimorfism. Metode virtuale ........................................................................................................ 80
I.3.6. Principiile programrii orientate pe obiecte ................................................................................. 81
I.4. STRUCTURA UNEI APLICAII ORIENTAT PE OBIECTE N C#..................................................................... 81
I.4.1. Clas de baz i clase derivate...................................................................................................... 82
I.4.2. Constructori................................................................................................................................... 82
I.4.3. Suprancrcarea 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 FUNCII GENERICE .................................................................................................................. 111
I.7. DERIVAREA CLASELOR (MOTENIRE) .................................................................................................... 114
I.7.1. Principiile motenirii ................................................................................................................... 114
I.7.2. Accesibilitatea membrilor motenii ............................................................................................ 116
I.7.3. Metode ......................................................................................................................................... 118
I.7.4. Interfee........................................................................................................................................ 119
I.8. TRATAREA EXCEPIILOR N C#.............................................................................................................. 121
I.8.1. Aruncarea i prinderea excepiilor.............................................................................................. 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 motenire ......................................................................................................... 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 PROGRAMRII VIZUALE.............................................................................. 133
II.2.
MEDIUL DE DEZVOLTARE VISUAL C# (PREZENTAREA INTERFEEI) .................................................. 134
II.3.
ELEMENTELE POO N CONTEXT VIZUAL ........................................................................................... 136
Barele de instrumente ................................................................................................................................. 138
II.4.
CONSTRUIREA INTERFEEI UTILIZATOR ............................................................................................ 143
II.4.1. Ferestre........................................................................................................................................ 143
II.4.2. Controale ..................................................................................................................................... 146
II.5.
APLICAII ......................................................................................................................................... 147
II.5.1. Numere pare ................................................................................................................................ 147
II.5.2. Proprieti comune ale controalelor i formularelor: ................................................................. 149
II.5.3. Metode i evenimente................................................................................................................... 150
1

II.5.4. Obiecte grafice............................................................................................................................. 172


II.5.5. Validarea informaiilor de la utilizator ....................................................................................... 174
II.5.6. MessageBox ................................................................................................................................. 175
II.5.7. Interfa definit de ctre utilizator............................................................................................ 178
II.5.8. Browser creat de ctre 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. Operaii specifice prelucrrii 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.
APLICAIE FINAL ............................................................................................................................ 226

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 aplicaiilor desktop Windows i aplicaiilor WEB.
Tehnologia .NET pune laolalt mai multe tehnologii (ASP, XML, OOP, SOAP, WDSL, UDDI)
i limbaje de programare (VB, C++, C#, J#) asigurnd, totodat, att portabilitatea codului compilat
ntre diferite calculatoare cu sistem Windows, ct 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, pn 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 aplicaii pe platforma .NET este bine s avem 3 componente eseniale:

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, aplicaiilor Web i aplicaiilor desktop
Windows.

Cnd dezvoltm aplicaii .NET, putem utiliza:

Servere specializate - un set de servere Enterprise .NET (din familia SQL Server 2000,
Exchange 2000 etc), care pun la dispoziie funcii de stocare a bazelor de date, email,
aplicaii B2B (Bussiness to Bussiness comer electronic ntre partenerii unei afaceri).

Servicii Web (n special comerciale), utile n aplicaii 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
aplicaiile .NET i sistemul de operare i actualmente conine:

Limbajele C#, VB.NET, C++ i J#. Pentru a fi integrate n platforma .NET, toate aceste
limbaje respect nite specificaii OOP numite Common Type System (CTS). Ele au ca
elemente de baz: clase, interfee, delegri, tipuri valoare i referin, iar ca mecanisme:
motenire, polimorfism i tratarea excepiilor.
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 aplicaiilor desktop sau Web, numit


Framework Class Library (FCL).

I.1.1.

Arhitectura .NET Framework

Servicii WEB

Formulare

FCL

Data and XML classes


(ADO.NET, SQL, XML etc.)
Framework Base Classes
(IO, securitate, fire de execuie, colecii etc.)
Common Language Runtime
(execepii, validri de tipuri,compilatoare JIT)

CLR

Componenta .NET Framework este format din compilatoare, biblioteci i alte executabile utile
n rularea aplicaiilor .NET. Fiierele corespunztoare se afl, n general, n directorul
C:\WINDOWS\Microsoft. NET\Framework\V2.0. (corespunztor 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 obinut are
extensia "exe", dar nu este direct executabil, ci respect formatul unic MSIL.
CLR include o main virtual asemntoare cu o main Java, ce execut instruciunile IL
rezultate n urma compilrii. Maina folosete un compilator special JIT (Just In Time).
Compilatorul JIT analizeaz codul IL corespunztor apelului unei metode i produce codul main
adecvat i eficient. El recunoate secvenele de cod pentru care s-a obinut deja codul main
adecvat, permind reutilizarea acestuia fr recompilare, ceea ce face ca, pe parcursul rulrii,
aplicaiile .NET s fie din ce n ce mai rapide.
Faptul c programul IL produs de diferitele limbaje este foarte asemntor are ca rezultat
interoperabilitatea ntre aceste limbaje. Astfel, clasele i obiectele create ntr-un limbaj specific
.NET pot fi utilizate cu succes n altul.

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 aplicaiilor .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 rnd pentru c ne ofer instrumente pe care le putem folosi i n alte programe,
ofer acces uor la baze de date, permite realizarea desenelor sau a altor elemente grafice.
Spaiul de nume System.Windows.Forms conine instrumente (controale) ce permit implementarea
elementelor interfeei grafice cu utilizatorul. Folosind aceste controale, putei proiecta i dezvolta
rapid i interactiv, elementele interfeei grafice. Tot .NET v ofer clase care efectueaz
majoritatea sarcinilor uzuale cu care se confrunt programele i care plictisesc i fur timpul
programatorilor, reducnd astfel timpul necesar dezvoltrii aplicaiilor.

I.2.

Introducere n limbajul C#
I.2.1.

Caracterizare

Limbajul C# a fost dezvoltat de o echip restrns de ingineri de la Microsoft, echip din


care s-a evideniat 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
programrii profesioniste.
Principiile de baz ale programrii orientate pe obiecte (NCAPSULARE, MOTENIRE,
POLIMORFISM) sunt elemente fundamentale ale programrii C#. n mare, limbajul motenete
sintaxa i principiile de programare din C++. Sunt o serie de tipuri noi de date sau funciuni diferite
ale datelor din C++, iar n spiritul realizrii unor secvene de cod sigure (safe), unele funciuni au
fost adugate (de exemplu, interfee i delegri), diversificate (tipul struct), modificate (tipul string)
sau chiar eliminate (motenirea multipl i pointerii ctre funcii). Unele funciuni (cum ar fi accesul
5

direct la memorie folosind pointeri) au fost pstrate, dar secvenele de cod corespunztoare se
consider nesigure.

I.2.2.

Crearea aplicaiilor consol

Pentru a realiza aplicaii consol (ca i cele din Borland Pascal sau Borland C) n mediul de
dezvoltare Visual Studio, trebuie s instalm o versiune a acestuia, eventual mediul free Microsoft
Visual C# 2008 Express Edition de la adresa http://www.microsoft.com/express/download/
Dup lansarea aplicaiei, din meniul File se alege opiunea NewProject apoi alegem
ConsoleApplication, modificnd numele aplicaiei n caseta Name.

Cnd creai o aplicaie consol, se genereaz un fiier cu extensia .cs. n cazul nostru, s-a
generat fiierul Primul.cs. Extensia cs provine de la C Sharp. Redenumirea lui se poate realiza

din fereastra Solution Explorer, pe care o putei afia cu ajutorul combinaiei 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)
{
}
}
}

Completai funcia Main cu urmtoarea linie de program:


Console.WriteLine("Primul program");

Vei observa c n scrierea programului suntei asistai de IntelliSense, ajutorul contextual.

Pentru compilarea programului, selectai Build din meniul principal sau apsai tasta F6. n
cazul n care avei erori, acestea sunt afiate n fereastra Error List. Efectund dublu-clic pe
fiecare eroare n parte, cursorul din program se poziioneaz pe linia coninnd eroarea.
Rularea programului se poate realiza n mai multe moduri:

rapid fr 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 pn la linia marcat ca punct de ntrerupere (Toggle Breakpoint F9 pe
linia respectiv i apoi Start Debugging F6). ncetarea urmririi pas cu pas (Stop
Debugging Shift+F5) permite ieirea din modul depanare i revenirea la modul normal
de lucru. Toate opiunile i rulare i depanare se gsesc n meniul Debug al mediului de
programare.
7

Icoanele din IntelliSense i semnificaia lor

I.2.3.

Structura unui program C#

Majoritatea crilor care trateaz limbaje de programare ncep cu un exemplu, devenit


celebru, aprut pentru prima dat n ediia din 1978 a crii The C Programming Language a lui
Brian W. Kernighan i Dennis M. Ritchie, prinii limbajului C. Vom prezenta i noi acest exemplu
adaptat la limbajul C#:
1
2
3
4
5
6
7
8
9
10
11
12

using System;
namespace HelloWorld
{
class Program
{
static void Main()
{
Console.WriteLine("Hello World!");
}
}
}

O aplicaie C#

este format din una sau mai multe clase, grupate n spaii de nume

(namespaces). Este obligatoriu ca doar una din aceste clase s conin un punct de intrare
(entry point), i anume metoda (funcia) Main.

Clasa (class), n termeni simplificai, reprezint principalul element structural i de


organizare n limbajele orientate spre obiecte, grupnd date ct i funcii care prelucreaz
respectivele date.
Spaiul de nume (Namespaces): din raiuni practice, programele mari, sunt divizate n
module, dezvoltate separat, de mai multe persoane. Din acest motiv, exist posibilitatea de a
aprea identificatori cu acelai nume. Pentru a evita erori furnizate din acest motiv, n 1955
limbajul C++ introduce noiunea i cuvntul cheie namespace. Fiecare mulime de definiii dintr-o
librrie sau program este grupat ntr-un spaiu de nume, existnd astfel posibilitatea de a avea
ntr-un program definiii cu nume identic, dar situate n alte spaii de nume. n cazul n care, ntr-o
aplicaie, unele clase sunt deja definite, ele se pot folosi importnd spaiile de nume care conin
definiiile acestora. Mai menionm faptul c un spaiu de nume poate conine mai multe spaii de
nume.

S comentm programul de mai sus:


linia 1: este o directiv care specific faptul c se vor folosi clase incluse n spaiul de nume
System. n cazul nostru, se va folosi clasa Console.
linia 3: spaiul nostru de nume
linia 5: orice program C# este alctuit 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 operaiile de intrare/ieire.
Aici se apeleaz metoda WriteLine din aceast clas, pentru afiarea
mesajului dorit pe ecran.
namespace

n C#, simplificat vorbind, un program poate


fi privit ca avnd mai multe straturi: avem cod n

class

interiorul metodelor, care, la rndul lor, se afl n


interiorul

claselor,

aflate

metod

interiorul

namespaces-urilor.
Convenie:

cod
S-a

adoptat

urmtoarea

convenie de scriere: n cazul n care folosim nume


compuse din mai multe cuvinte, fiecare cuvnt
este

scris

cu

majuscul:

HelloWorld,

WriteLine. Aceast convenie poart numele de


Convenie Pascal. Asemntoare este Convenia cmil, cu diferena c primul caracter din
primul cuvnt este liter mic.

I.2.4.

Sintaxa limbajului

Ca i limbajul C++ cu care se nrudete, 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 semnificaii 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 rnd prin folosirea //. Tot ce urmeaz dup caracterele // sunt
considerate, din acel loc pn la sfritul rndului, drept comentarii.
// Acesta este un comentariu pe un singur rand

comentariu pe mai multe rnduri prin folosirea /* i */. Orice text cuprins ntre
simbolurile menionate mai sus se consider a fi comentariu. Simbolurile /* reprezint
nceputul comentariului, iar */ sfritul respectivului comentariu.
/* Acesta este un
comentariu care se
intinde pe mai multe randuri */

creare document n format XML folosind ///.

Nepropunndu-ne s intrm n

amnunte, amintim c XML (eXtensible Markup Language) a fost proiectat n scopul


transferului de date ntre aplicaii pe Internet, fiind un model de stocare a datelor
nestructurate i semi-structurate.

I.2.4.2. Nume
Definiie: Prin nume dat unei variabile, clase, metode etc. nelegem o succesiune de
caractere care ndeplinete urmtoarele 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 dect 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 puin un caracter (fie el i liter mic ce
difer de aceeai liter majuscul).

Convenii pentru nume:

n cazul numelor claselor, metodelor, a proprietilor, enumerrilor, interfeelor, spaiilor


de nume, fiecare cuvnt 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 predefinii cu semnificaie special pentru compilator.
Definim n C# urmtoarele cuvinte cheie:
abstract
byte
class
delegate
event
fixed
if
internal
new
override
readonly
short
struct
try
unsafe
volatile

as
case
const
do
explicit
float
implicit
is
null
params
ref
sizeof
switch
typeof
ushort
while

base
catch
continue
double
extern
for
in
lock
object
private
return
stackalloc
this
uint
using

bool
char
decimal
else
false
foreach
int
long
operator
protected
sbyte
static
throw
ulong
virtual

break
checked
default
enum
finally
goto
interface
namespace
out
public
sealed
string
true
unchecked
void

Pentru a da semnificaii specifice codului, n C# avem i cuvinte cheie contextuale:

ascending
get
on
value

by
group
orderby
where

descending
into
partial
yield

equals
join
select

from
let
set

n general, cuvintele cheie nu pot fi folosite n programele pe care le scriem, dndu-le o


alt semnificaie. n cazul n care, totui, dorim s le dm o alt semnificaie, va trebui s le scriem
cu simbolul @ ca prefix. Datorit neclaritilor care pot s apar, se va evita folosirea cuvintelor
rezervate n alte scopuri.

11

I.2.4.3. Constante
n C# exist dou modaliti de declarare a constantelor: folosind const sau folosind
modificatorul readonly. Constantele declarate cu const trebuie s fie iniializate la declararea
lor.
Exemplul 1:
const int x;
const int x = 13;

//gresit, constanta nu a fost initializata


//corect

Constantele declarate cu ajutorul lui readonly sunt doar variabilele membre ale claselor,
ele putnd fi iniializate doar de ctre constructorii claselor respective.

Exemplul 2:
readonly int x;
readonly int x = 13;

//corect
//corect

I.2.4.4. Variabile

O variabil n C# poate s conin fie o valoare a unui tip elementar, fie o referin la un
obiect. C# este case sensitive, deci face distincie ntre litere mari i mici.

Exemplul 3:
int Salut;
int Azi_si_maine;
char caracter;

I.2.4.6. Expresii i operatori


Definiie: Prin expresie se nelege o secven format din operatori i operanzi. Un
operator este un simbol ce indic aciunea care se efectueaz, iar operandul este valoarea
asupra creia se execut operaia.
Operatorii se mpart n trei categorii:
12

Unari: - acioneaz asupra unui singur operand

Binari: - acioneaz ntre doi operanzi

Ternari: - acioneaz asupra a trei operanzi; exist un singur operator ternar i acesta
este ?:

n C# sunt definii mai muli operatori. n cazul n care ntr-o expresie nu intervin paranteze,
operaiile se execut conform prioritii operatorilor. n cazul n care sunt mai muli operatori cu
aceeai prioritate, evaluarea expresiei se realizeaz de la stnga la dreapta. n tabelul alturat
prioritatea descrete de la 0 la 13.
Tabelul de prioriti:
Prioritate
0
1
2
3
4
5
6
7
8
9
10
11
12
13

Tip
Primar
Unar
Multiplicativ
Aditiv
De deplasare
Relaional
De egalitate
AND (SI) logic
XOR (SAU exclusiv)
logic
OR (SAU) logic
AND (SI)
condiional
OR (SAU)
condiional
Condiional(ternar)
atribuire simpl
atribuire compus

Operatori
( ) [ ] f() . x++ x-- new typeof sizeof
checked unchecked ->
+ - ! ~ ++x --x (tip) true false & sizeof
* / %
+ << >>
< > <= >= is as
== !=
&
^

Asociativitate

|
&&

||

?:
=
*= /= %= += -= ^= &= <<= >>=

|=

Exemplul 4: folosind operatorul ternar ?:, s se decid dac un numr citit de la tastatur este
pozitiv sau negativ.
Indicaii:

Sintaxa acestui operator este: (condiie) ? (expr_1): (expr_2) cu semnificaia se evalueaz


condiie, dac ea este adevrat se execut expr_1, altfel expr_2

int.Parse convertete 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 rulrii programului obinem:

Exemplul 5: Folosind operatorul %, s se verifice dac un numr este par sau impar. Observaie:
Convert.ToInt32 convertete 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: Urmtorul program afieaz la consol tabelul de adevr pentru operatorul logic &.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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}" + " = "
v1,
v1 = true; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
v1 = false; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
v1 = false; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
Console.ReadKey();
}
}
}

+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);

I.2.4.7. Opiuni de afiare


Pentru a avea control asupra modului de afiare a informaiei numerice, se poate folosi
urmtoarea form a lui WriteLine():
WriteLine("sir",var1,var2,, varn);

unde sir este format din dou elemente:

caracterele afiabile obinuite coninute n mesaje

15

specificatorii de format ce au forma general {nr_var,width:fmt} unde nr_var


precizeaz numrul variabilei (parametrului) care trebuie afiat ncepnd cu 0, width
stabilete limea cmpului de afiare, iar fmt stabilete 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 afiare ales #.### va produce afiarea 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 urmtor realizeaz suma a dou valori numerice fr semn cu reprezentare
pe 8 bii. Rezultatul va fi reinut pe 64 bii
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Text;

namespace Exemplul_9
{
class Program
{
static void Main(string[] args)
{
byte a = 13; // byte intreg fara semn pe 8 bii
byte b = 20;
long c;
// intreg cu semn pe 64 bii
c = a + b;
Console.WriteLine("{0} + {1} = {2}", a, b, c);
Console.WriteLine("Suma intregilor pe 8 bii se reprezinta pe 64
bii");
}
}
}

17

I.2.4.8.1. Conversiile implicite


Regula dup care se efectueaz conversiile implicite este descris de tabelul urmtor:
din
sbyte
byte
short
ushort
int
uint
long
char
float
ulong

n
short, int, long, float, double, decimal
short, ushort, int, uint, long, ulong, float, double, decimal
int, long, float, double, decimal
int, uint, long, ulong, float, double, decimal
long, float, double, decimal
long, ulong, float, double, decimal
float, double, decimal
ushort, int, uint, long, ulong, float, double, decimal
double
float, double, decimal

I.2.4.8.2. Conversia explicit


Se realizeaz prin intermediul unei expresii cast (care va fi studiat mai trziu), atunci cnd
nu exist posibilitatea unei conversii implicite.

din

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 rulrii programului, se va obine:

n cazul n care nu s-ar fi folosit operatorul cast, rezultatul - evident eronat - ar fi fost:

Des ntlnit 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 numr 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
using
using
using

System;
System.Collections.Generic;
System.Linq;
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);

fv, srez);

Console.WriteLine("Explicite:");
srez = (short)fv;
Console.WriteLine("float spre short folosind cast {0} spre {1}",

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 pstreaz pe
stiv, se produce ambalarea n interiorul unei instane de tip referin, care se pstreaz 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

iniializeaz o variabil de tip valoare, care va conine

valoarea 13, valoare care va fi stocat pe stiv. Linia a

13
int i=13;

doua creeaz o referin ctre un obiect alocat n heap,


care va conine att valoarea 13, ct i informaia

ob

referitoare la tipul de dat coninut.

object ob=i;

21

heap

int
13

Se poate determina tipul pentru care s-a fcut 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 coninut.


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 rulrii se obine:

Exemplul 17: Prin conversia de tip unboxing, obiectul ob poate fi asignat variabilei ntregi i:
int i = 13;
object ob = i;
i = (int)ob;

//boxing implicit
//unboxing explicit

22

I.2.4.8.4. Conversii ntre numere i iruri de caractere


Limbajul C# ofer posibilitatea efecturii de conversii ntre numere i iruri de caractere.
Sintaxa pentru conversia numr n ir de caractere:
numr ir

+ numr

Pentru conversia invers, adic din ir de caractere n numr, sintaxa este:


ir
ir
ir
ir

int
long
double
float

int.Parse(ir) sau Int32.Parse(ir)


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

Observaie: n cazul n care irul de caractere nu reprezint un numr valid, conversia


acestui ir la numr va eua.

Exemplul 18:

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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

Observaie: Toate tipurile de date sunt derivate din tipul System.Object


Toate tipurile valoare sunt derivate din clasa System.ValueType, derivat la rndul ei
din clasa Object (alias pentru System.Object).
Pentru tipurile valoare, declararea unei variabile implic i alocarea de spaiu. Dac
iniial, variabilele conin valoarea implicit specific tipului, la atribuire, se face o copie a datelor n
variabila destinaie care nu mai este legat de variabila iniial. Acest proces se numete
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 spaiu: iniial, referin ele sunt null i trebuie alocat explicit
memorie pentru obiectele propriu-zise. n plus, la atribuire, este copiat referina n variabila

25

destinaie, dar obiectul spre care indic rmne acelai (aliasing). Aceste reguli poarta
denumirea de reference semantics.
Exemplul 20: Pentru exemplificarea celor de mai sus, pentru tipurile referin, vom folosi clasa
StringBuilder.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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# conine un set de tipuri predefinite (int, bool etc.) i permite definirea unor
tipuri proprii (enum, struct, class etc.).

26

Tipuri simple predefinite


Tip
object
string
sbyte
short
int
long
byte
ushort
uint
ulong
float
double
bool
char
decimal

Descriere

Alias pentru tipul struct


din spaiul de nume System

rdcina oricrui tip


secven de caractere Unicode
tip ntreg cu semn, pe 8 bii
tip ntreg cu semn, pe 16 bii
tip ntreg cu semn pe, 32 bii
tip ntreg cu semn, pe 64 de bii
tip ntreg fr semn, pe 8 bii
tip ntreg fr semn, pe 16 bii
tip ntreg fr semn, pe 32 bii
tip ntreg fr semn, pe 64 bii
tip cu virgul mobil, simpl precizie, pe 32 bii
(8 pentru exponent, 24 pentru mantis)
tip cu virgul mobil, dubl precizie, pe 64 bii
(11 pentru exponent, 53 pentru mantis)
tip boolean
tip caracter din setul Unicode, pe 16 bii
tip zecimal, pe 128 bii (96 pentru mantis), 28
de cifre semnificative

System.String
System.Sbyte
System.Int16
System.Int32
System.Int64
System.Byte
System.Int16
System.Uint32
System.Uint64
System.Single
System.Double
System.Boolean
System.Char
System.Decimal

Domeniul de valori pentru tipurile numerice:


Tip
sbyte
short
int
long
byte
ushort
uint
ulong
float
double
decimal

Domeniul de valori
-128; 127
-32768; 32767
-2147483648; 2147483647
-9223372036854775808; 9223372036854775807
0; 255
0; 65535
0; 4294967295
0; 18446744073709551615
-3.402823E+38; 3.402823E+38
-1.79769313486232E+308; 1.79769313486232E+308
-79228162514264337593543950335;
79228162514264337593543950335

O valoare se asigneaz dup urmtoarele reguli:


Sufix
nu are
u, U
L, L
ul, lu, Ul, lU, UL, LU, Lu

Tip
int, uint, long, ulong
uint, ulong
long, ulong
ulong

27

Exemplul 21:
string s = Salut!
long a = 10;
long b = 13L;
ulong c = 12;
ulong d = 15U;
ulong e = 16L;
ulong f = 17UL;

float g = 1.234F;
double h = 1.234;
double i = 1.234D;
bool cond1 = true;
bool cond2 = false;
decimal j = 1.234M;

I.2.5.1.2. Tipul enumerare


Tipul enumerare, asemntor cu cel din C++, se definete de ctre utilizator. Acest tip
permite utilizarea numelor care, sunt asociate unor valori numerice.
Enumerrile 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 enumerrii, acesta este considerat implicit int.
Specificarea tipului se face dup numele enumerrii:
[atribute][modificatori]enum NumeEnumerare [: Tip]
{
lista
}

n ceea ce urmeaz, vom considera enum fr elementele opionale.


Folosirea tipului enumerare impune urmtoarele observaii:

n mod implicit, valoarea primului membru al enumerrii este 0, iar fiecare variabil care
urmeaz are valoarea (implicit) mai mare cu o unitate dect precedenta.

valorile folosite pentru iniializri trebuie s fac parte din domeniul de valori al tipului
enum

nu se admit referine circulare


enum ValoriCirculare
{
a = b,
b
}

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


Asemntor celor cunoscute din C++, tipul structur poate s conin declaraii de constante,
cmpuri, metode, proprieti, 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 vzut mai sus c pentru tipurile valoare, la declararea unei variabile, aceasta
conine valoarea implicit a tipului. Sunt cazuri n care se dorete ca, la declarare, valoarea
implicit a variabilei s fie nedefinit.
n

C#

exist

astfel

de

posibilitate,

folosind

Concret, o declaraie de forma:


System.Nullable<T> var;

este echivalent cu
T? var;

unde T este un tip valoare.


29

structura

System.Nullable<T>.

Aceste tipuri nulabile conin dou proprieti:

proprietate HasValue, care indic dac valoarea intern este diferit sau nu de null

proprietatea Value, care va conine valoarea propriu zis.


Legat de aceast noiune, s-a mai introdus operatorul binar ??

a ?? b

cu semnificaia: dac a este null b este evaluat i constituie rezultatul expresiei, altfel
rezultatul este a.

I.2.6. Instruciuni condiionale, de iteraie i de control


Ne referim aici la instruciunile construite folosind cuvintele cheie: if, else, do, while,
switch, case, default, for, foreach, in, break, continue, goto.

I.2.6.1. Instruciunea if
Instruciunea 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
x2

x3

y1 1
y2 1 = 0
y3 1

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

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 numr ntreg x este ntr-un interval dat [a, b]
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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. Instruciunea switch


n cazul instruciunii switch n C/C++, dac la finalul instruciunilor dintr-o ramur case nu
exist break, se trece la urmtorul case. n C# se semnaleaz eroare. Exist i aici posibilitatea
de a face verificri multiple (n sensul de a trece la verificarea urmtoarei condiii din case) doar
dac case-ul nu conine instruciuni:
Instruciunea switch admite n C# variabil de tip ir de caractere care s fie comparat cu
irurile de caractere din case-uri:
Exemplul 26: Programul urmtor afieaz ultima cifr a numrului xn, unde x i n sunt numere
naturale citite de la tastatur.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 ");
case 1: Console.WriteLine(" 2 ");
case 2: Console.WriteLine(" 4 ");
case 3: Console.WriteLine(" 8 ");
}
break;

33

break;
break;
break;
break;

case 3:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 ");
case 1: Console.WriteLine(" 3 ");
case 2: Console.WriteLine(" 9 ");
case 3: Console.WriteLine(" 7 ");
}
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 ");
case 1: Console.WriteLine(" 7 ");
case 2: Console.WriteLine(" 9 ");
case 3: Console.WriteLine(" 3 ");
}
break;
case 8:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 ");
case 1: Console.WriteLine(" 8 ");
case 2: Console.WriteLine(" 4 ");
case 3: Console.WriteLine(" 2 ");
}
break;
case 9:
if (n % 2 == 0) Console.WriteLine(" 1
else Console.WriteLine(" 9 ");
break;
}
}
}
using
using
using
using

}
System;
System.Collections.Generic;
System.Linq;
System.Text;

34

break;
break;
break;
break;

");

break;
break;
break;
break;

break;
break;
break;
break;

");

Exemplul 27: Programul urmtor efectueaz calculele corespunztoare 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. Instruciunea while


Instruciunea while are sintaxa:
while (conditie) Instructiuni;

Ct timp conditie este ndeplinit se execut Instructiuni.

Exemplul 28: S se afieze 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 numr cte cifre pare are un numr 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
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 numr ntreg pozitiv, citit de la tastatur, s se elimine cifra cea mai mic i
s se afieze numrul rezultat n urma acestei operaii.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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. Instruciunea do while


Instruciunea do while are sintaxa:
do
Instructiuni;
while(conditie)

Se execut Instructiuni dup care se verific conditie. Dac aceasta este adevrat,
ciclul se reia, altfel ciclul se termin.

39

Exemplul 32: Asemntor cu exerciiul 28, s se afieze 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 afieze numerele cu proprietatea de a fi palindroame, pn la o valoare citit


de la tastatur. De asemenea, s se afieze i numrul lor.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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. Instruciunea for


Instruciunea for are sintaxa:
for(initializareCiclu; conditieFinal; reinitializareCiclu)
Instructiune

41

Exemplul 34: Ne propunem, s afim 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 numrul lor, cuprinse ntre dou valori
ntregi citite de la tastatur.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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
using
using
using

System;
System.Collections.Generic;
System.Linq;
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("*");
case 1: Console.Write("$");
case 2: Console.Write("o");
case 3: Console.Write("@");
}

}
Console.WriteLine();
}
}

44

break;
break;
break;
break;

I.2.6.6. Instruciunea foreach


O instruciune nou, pe care o aduce limbajul C#, este foreach. Aceast instruciune
enumer elementele dintr-o colecie, executnd o instruciune pentru fiecare element. Elementul
care se extrage este de tip read-only, neputnd fi transmis ca parametru i nici aplicat un operator
care s-i schimbe valoarea.

45

Pentru a vedea cum acioneaz, o vom compara cu instruciunea cunoscut for.


Considerm un vector nume format din iruri de caractere:
string[] nume = {"Ana", "Ionel", "Maria"}

Afiarea irului folosind for:


for(int i=0; i<nume.Length; i++)
Console.Write("{0} ", nume[i]);

Acelai rezultat l obinem folosind instruciunea foreach:


foreach (string copil in nume)
Console.Write("{0} ", copil);

Mai dm 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 afia numrul de cuvinte i


fiecare cuvnt 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. Instruciunea goto


Instruciunea goto poate fi folosit, n C#, pentru efectuarea unor salturi, n instruciunea
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. Instruciunea continue


Instruciunea continue permite reluarea iteraiei celei mai apropiate instruciuni 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. Instruciunile try-catch-finally i throw


Prin excepie se nelege un obiect care ncapsuleaz informaii despre situaii anormale. Ea
se folosete pentru a semnala contextul n care apare o situaie special.
Exemple: erori la deschiderea unor fiiere a cror nume este greit, mprire la 0 etc. Aceste
erori se pot manipula astfel nct programul s nu se prbueasc.
Cnd o metod ntlnete o situaie dintre cele menionate mai sus, se va arunca o
excepie care trebuie sesizat i tratat. Limbajul C# poate arunca ca excepii obiecte de tip
System.Exception sau derivate ale acestuia. Aruncarea excepiilor se face cu instruciunea
throw
throw new System.Exception();

Prinderea i tratarea excepiilor se face folosind un bloc catch. Pot exista mai multe blocuri
catch, fiecare dintre ele prinde i trateaz o excepie.

48

Pentru a garanta c un anumit cod se va executa indiferent dac totul decurge normal sau
apare o excepie, acest cod se va pune n blocul finally care se va executa n orice situaie.

Exemplul 40:
Presupunem c dorim s citim fiierul Gigel.txt
using System;
using System.IO;
namespace Exemplul_40
{
class tryCatch
{
static void Main(string[] args)
{
File.OpenRead("Gigel.txt");
}
}
}

ncercnd s compilm obinem:

Pentru a remedia aceast eroare, vom prinde excepia, punnd ntr-un bloc try linia care a
furnizat-o.
Putem vizualiza mesajul produs de excepia ntlnit:

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

Bineneles 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, aruncnd o excepie (instruciunea
throw) sau putem profita de mecanismul de tratare a erorilor pentru a implementa un mecanism
de validare a datelor prin generarea unei excepii proprii pe care, de asemenea, o aruncm n
momentul nendeplinirii unor condiii puse asupra datelor.
Clasa System.Exception i derivate ale acesteia servesc la tratarea adecvat i
diversificat a excepiilor.

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 operaiile asupra tablourilor, apelnd metode ale System.Array.
Declararea unui tablou unidimensional se face astfel:
Tip[] nume;

Prin aceast declaraie nu se aloc i spaiu pentru memorare. Pentru aceasta, tabloul
trebuie instaniat:
nume = new Tip[NumarElemente];

Se pot face n acelai timp operaiile de declarare, instaniere i iniializare:


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

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

Exemplul 41: Crearea, sortarea i afiarea 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++)
Console.Write("{0,3}", v[i]);

//afisarea vectorului v

Afiarea se poate face i cu ajutorul lui foreach:


foreach (int i in v)
Console.Write("{0,3}",i);

52

Exemplul 42: S se afieze numrul de elemente de pe a doua linie a tabloului i numrul 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 afieze primele n+1 linii din triunghiul lui PASCAL(n20).
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 numr natural n dat se afieaz toate numerele
prime mai mici dect 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
obine acest ir tiem mai nti toi multiplii lui 2, apoi ai lui 3 .a.m.d. n final rmn numai
numerele prime din intervalul [2,n]. Noiunea de tiere 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) pn la apartamentul n care locuiete. El


poate urca pind pe treapta urmtoare sau srind peste o treapt. n cte moduri poate urca Ionel
cele n trepte?
Dac notm cu f[i] numrul de moduri n care poate urca copilul i trepte, observm 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 numrul de moduri, vom nsuma n cte moduri poate ajunge pe treapta i-1 cu numrul
de modaliti 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 frecvena sa de apariie

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


}
}
}

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}

56

Exemplul 47: Operaii cu elementele unui vector: citire, afiare, eliminare elemente de valoare 0,
inserare dup fiecare valoare a celei mai apropiate puteri ale lui 2 (dac cele dou puteri sunt la
aceeai distan fa de numr 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 distincie ntre tablouri regulate i
tablouri neregulate (tablouri de tablouri)
Declararea n cazul tablourilor regulate bidimensionale se face astfel:
Tip[,] nume;

iar instanierea:
nume = new Tip[Linii,Coloane];

Accesul:
nume[indice1,indice2]

58

Exemplu: Declararea instanierea i iniializarea


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 instanierea i iniializarea:


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 }

Observaie: 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 utilizai frecvent n aplicaiile grafice.

Exemplul 48: Descompunerea unui numr n sum de numere naturale consecutive. Se citete un
numr natural n. S se memoreze toate posibilitile de descompunere a numrului n n sum de
numere consecutive.
Dac numrul n se scrie ca sum de numere naturale consecutive, atunci rezult c exist
i,kN* astfel nct
i+(i+1)+(i+2)+(i+3)++(k)=n
(1+2+...+k)-(1+2+...+i-1)=nk*(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 ptratic, ale crei elemente ntregi se citesc de la tastatur, s se
determine:

maximul dintre valorile situate deasupra diagonalei principale

numrul 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 conine ntre ghilimele zero sau mai multe caractere, inclusiv secvene escape.
string a = "Acesta este un sir de caractere";
string b = "";
string nume = "Gigel";

63

Limbajul C# introduce, pe lng irurile regulate i cele de tip verbatim. n cazul n care
folosim multe secvene escape, putem utiliza irurile verbatim. Aceste iruri se folosesc n
special n cazul n care dorim s facem referiri la fiiere, la prelucrarea lor, la regitri. 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();
}
}
}

Secvenele escape permit reprezentarea caracterelor care nu au reprezentare grafic


precum i reprezentarea unor caractere speciale: backslash, caracterul apostrof, etc.
Secven
escape
\
\
\\
\0
\a
\b
\f
\n
\r

Efect
apostrof
ghilimele
backslash
null
alarm
backspace
form feed pagin nou
new line linie nou
carriage return nceput de rnd
64

\t
\u
\v
\x

horizontal tab tab orizontal


caracter unicode
vertical tab tab vertical
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 !=.
Definiie: dou iruri se consider egale dac sunt amndou null, sau dac amndou
au aceeai lungime i pe fiecare poziie au caractere respectiv identice. n caz contrar irurile se
consider diferite.
Exemplul 50: Exemplul urmtor demonstraz c operatorul == este definit pentru a compara
valoarea obiectelor string i nu referina lor
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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. Funcii importante pentru iruri


Clasa String pune la dispoziia utilizatorului mai multe metode i proprieti care permit
prelucrarea irurilor de caractere. Dintre acestea amintim:

metode de comparare:
-

Compare

CompareOrdinal

CompareTo

metode pentru cutare:


-

EndsWith

StartsWith

IndexOf

LastIndexOf

metode care permit modificarea irului curent prin obinerea 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 lucrri i, dup cum tim returneaz un
ntreg care reprezint lungimea (numrul de caractere) irului.
66

Tabelul de mai jos prezint cteva dintre funciile (metodele) clasei String
Funcia (metod a clasei Strig)
string Concat(string u, string v)
int IndexOf(char c)
int IndexOf(string s)
string Insert(int a, string s)
string Remove(int a, int b)
string Replace(string u, string v)
string Split(char[] c)
string Substring(int index)
string Substring(int a, int b)
string ToLower()
string ToUpper()
string Trim()
string TrimEnd()
string TrimStart()

Descrierea
returneaz un nou ir obinut prin concatenarea
irurilor u i v
returneaz indicele primei apariii a caracterului
c n ir
returneaz indicele primei apariii a subirului s
returneaz un nou ir obinut din cel iniial prin
inserarea n irul iniial, ncepnd cu poziia a,
a irului s
returneaz un nou ir obinut din cel iniial prin
eliminarea, ncepnd cu poziia a, pe o lungime
de b caractere
returneaz un nou ir obinut din cel iniial prin
prin nlocuirea subirului u cu irul v
mparte un ir n funcie de delimitatorii c
returneaz un nou ir care este un subir al
irului ini ial ncepnd cu indicele index
returneaz un nou ir care este un subir al
irului iniial, ncepnd de pe poziia a, pe
lungimea b caractere
returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la minuscule
returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la majuscule
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la nceputul i
sfritul irului ini ial
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la sfritul irului
ini ial
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la nceputul irului
ini ial

Exemplul 51: Exemplificm aplicarea funciilor de mai sus:


using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 urmtor 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 aceeai textur. Dou
cuvinte au aceeai textur dac au aceeai lungime i toate caracterele corespondente au acelai
tip. Nu se face distincie ntre litere mari, litere mici.
Ex : acum i elev au aceeai 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 mulimea { ' ', ',', ';'}.
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 cutri/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 informaiilor n fiiere


I.2.9.1. Administrarea fiierelor
Tehnica de citire i scriere a datelor n i din fiiere, utilizat pentru a pstra aceste
informaii, reprezint administrarea fiierelor.
Pentru accesarea unui fiier de pe disc se folosesc funcii din spaiul de nume System.IO.
n acest spaiu exist mai multe clase: File, StreamWriter, BinaryReader i
BinaryWriter.
Aceste clase sunt folosite pentru operaiile de intrare-ieire cu fiiere.
Obiectul File este o reprezentare a unui fiier de pe disc, iar pentru a-l utiliza trebuie s l
conectm la un flux (stream).
Pentru a scrie datele pe disc, se ataeaz unui flux un obiect File. Astfel se face
administrarea datelor.
Limbajul C# ofer dou tipuri de fiiere: fiiere text i fiiere binare.

I.2.9.2. Scrierea i citirea datelor din fiiere text


Fiierele de ieire necesit utilizarea unui obiect StreamWriter.
Funcia CreateText(), ce face parte din clasa File, deschide un fiier i creeaz obiectul
StreamWriter.

Exemplul 56:
using
using
using
using

System;
System.Collections.Generic;
System.Text;
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 fiiere binare


Dac la fiierele text tipul de flux folosit era StreamWriter, la cele binare, pentru scrierea
datelor programul creeaz un obiect FileStream, la care trebuie ataat 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 programrii orientate pe obiecte


I.3.1. Evoluia tehnicilor de programare
Programarea nestructurat (un program simplu, ce utilizeaz numai variabile globale);
complicaiile apar cnd 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 obin avantaje privind depanarea i
reutilizarea codului i se aplic noi tehnici privind transferul parametrilor i vizibilitatea variabilelor;
complicaiile apar atunci cnd la program sunt asignai doi sau mai muli programatori care nu pot
lucra simultan pe un acelai fiier ce conine codul surs.
Programarea modular (gruparea subprogramelor cu funcionaliti similare n module,
implementate i depanate separat); se obin avantaje privind independena i ncapsularea (prin
separarea zonei de implementare, pstrnd 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)
subprog_1
subprog_2
subprog_3

(date+date2)
subprog_1
subprog_2

Se observ c modulele sunt centrate pe proceduri, acestea gestionnd 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 aplicaie nu este avantajoas.
Programarea orientat obiect POO (programe cu noi tipuri ce integreaz att datele, ct
i metodele asociate crerii, prelucrrii i distrugerii acestor date); se obin avantaje prin

75

abstractizarea programrii (programul nu mai este o succesiune de prelucrri, ci un ansamblu de


obiecte care prind
obiect1

obiect4

date1
met1

date4
met4

obiect3
date3
met3

obiect2
date2
met2

via, au diverse proprieti, sunt capabile de aciuni specifice i care interacioneaz n cadrul
programului); intervin tehnici noi privind instanierea, derivarea i polimorfismul tipurilor obiectuale.

I.3.2. Tipuri de date obiectuale. ncapsulare


Definiie: Un tip de date abstract (ADT) este o entitate caracterizat printr-o structur de
date i un ansamblu de operaii aplicabile acestor date.
Considernd, 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.
Totui se va ine cont doar de datele semnificative pentru problema dat. Astfel, culoarea ochilor
este irelevant n acest caz, n timp ce data naterii poate fi important. n aceeai idee, operaii
specifice ca se nregistreaz, comand on-line pot fi relevante, n timp ce operaia mnnc
nu este, n cazul nostru. Evident, nici nu se pun n discuie date sau operaii nespecifice (numrul
de laturi sau aciunea zboar).

Definiie: Operaiile care sunt accesibile din afara ADT formeaz interfaa acesteia. Astfel,
operaii interne cum ar fi conversia datei de natere la un numr standard calculat de la
01.01.1900 nu fac parte din interfaa tipului de date abstract, n timp ce operaia plaseaz o
comand on-line face parte, deoarece permite interaciunea cu alte obiecte (SITE, STOC etc.).
Definiie: Numim instan a unui tip de date abstract o concretizare a tipului respectiv,
format din valori efective ale datelor.
Definiie: Un tip de date obiectual este un tip de date care implementeaz un tip de date
abstract.

76

Definiie: Vom numi metode operaiile implementate n cadrul tipului de date abstract.
Definiie: Numim membri ai unui tip de date obiectual datele i metodele definite mai sus.
Folosirea unui tip de date obiectual tip presupune:

existena definiiei 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, vrful etc. Iar operaiile specifice pot fi: introducerea
n stiv (push) i extragerea din stiv (pop). La implementarea tipului STIVA, vom defini o structur
de date care s rein valorile memorate n stiv i cmpuri de date simple pentru: capacitate,
numr 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 vrful stivei, s testeze dac stiva este
vid sau dac stiva este plin etc.
Definiie: Crearea unei instane noi a unui tip obiectual, presupune operaii specifice de
construire a noului obiect, metoda corespunztoare purtnd numele de constructor.
Definiie: La desfiinarea unei instane i eliberarea spaiului de memorie aferent datelor
sale, se aplic o metod specific numit destructor (datorit tehnicii de suprancrcare, limbaje
de genul C++, Java i C# permit existena mai multor constructori ).
O aplicaie ce utilizeaz tipul obiectual STIVA, va putea construi dou sau mai multe stive
(de cri de joc, de exemplu), le va umple cu valori distincte, va muta valori dintr-o stiv n alta
dup o anumit regul desfiinnd orice stiv golit, pn ce rmne o singur stiv. De observat
c toate aceste prelucrri recurg la datele, constructorul, destructorul i la metodele din interfaa
tipului STIVA descris mai sus.
Definiii: Principalul tip obiectual ntlnit 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.
Definiie: La implementare, datele i metodele asociate trebuie s fie complet i corect
definite, astfel nct utilizatorul s nu fie nevoit s in cont de detalii ale acestei implementri. El
77

va accesa datele, prin intermediul proprietilor i va efectua operaiile, prin intermediul metodelor
puse la dispoziie de tipul obiectual definit. Spunem c tipurile de date obiectuale respect
principiul ncapsulrii.
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 operaiilor de depunere, extragere i aplicare a
dobnzilor. EL va utiliza unul sau mai multe conturi (instane ale tipului CONT), accesnd
proprietile i metodele din interfa, realizatorul tipului obiectual asumndu-i acele griji n
momentul definirii tipului CONT.
Permind extensia tipurilor de date abstracte, clasele pot avea la implementare:

date i metode caracteristice fiecrui 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: numrul de stive
generate, numrul maxim sau numrul 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 cte un exemplar al
membrului respectiv pentru fiecare instan a clasei, membrii statici sunt unici, fiind accesai n
comun de toate instanele clasei. Mai mult, membrii statici pot fi referii chiar i fr a crea vreo
instan a clasei respective.

I.3.3.Suprancrcare
Dei nu este o tehnic specific programrii orientat obiect, ea creeaz un anumit context
pentru metodele ce formeaz o clas i modul n care acestea pot fi (ca orice subprogram)
apelate.
Definiie: Prin suprancrcare se nelege posibilitatea de a defini n acelai domeniu de
vizibilitate mai multe funcii cu acelai nume, dar cu parametri diferii ca tip i/sau ca numr.
Definiie: Ansamblul format din numele funciei i lista sa de parametri reprezint o
modalitate unic de identificare numit semntur sau amprent.
Suprancrcarea permite obinerea 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 suprancrcarea operatorilor. Aceasta este o facilitate care reduce
78

diferenele dintre operarea la nivel abstract (cu DTA) i apelul metodei ce realizeaz aceast
operaie la nivel de implementare obiectual. Dei ajut la sporirea expresivitii codului, prin
suprancrcarea operatorilor i metodelor se pot crea i confuzii.
Apelul unei funcii care beneficiaz, prin suprancrcare, de dou sau mai multe semnturi
se realizeaz prin selecia funciei a crei semntur se potrivete cel mai bine cu lista de
parametri efectivi (de la apel).
Astfel, poate fi definit metoda comand on-line cu trei semnturi diferite:

comanda_online(cod_prod) cu un parametru ntreg (desemnnd 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. Motenire

Definiie: Pentru tipurile de date obiectuale class este posibil o operaie de extindere sau
specializare a comportamentului unei clase existente prin definirea unei clase noi ce motenete
datele i metodele clasei de baz, cu aceast ocazie putnd fi redefinii unii membri existeni sau
adugai unii membri noi. Operaia mai poart numele de derivare.
Definiii: Clasa din care se motenete se mai numete clas de baz sau superclas.
Clasa care motenete se numete subclas, clas derivat sau clas descendent.
Definiie: Ca i n Java, n C# o subclas poate moteni de la o singur superclas, adic
avem de-a face cu motenire simpl; aceeai superclas ns poate fi derivat n mai multe
subclase distincte. O subclas, la rndul 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 motenesc de la clasa de baz Object.
n contextul mecanismelor de motenire trebuie amintii modificatorii abstract i sealed
aplicai 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 obine obiecte prin operaia
de instaniere, n timp ce o clas sigilat (sealed) nu mai poate fi derivat (e un fel de terminal n
ierarhia claselor).

79

Definiie: O metod abstract este o metod pentru care nu este definit o implementare,
aceasta urmnd a fi realizat n clasele derivate din clasa curent care trebuie s fie i ea
abstract (virtual pur, conform terminologiei din C++).
Definiie: O metod sigilat este o metod care nu mai poate fi redefinit n clasele
derivate din clasa curent.

I.3.5. Polimorfism. Metode virtuale


Definiie: Folosind o extensie a sensului etimologic, un obiect polimorfic este cel capabil s
ia diferite forme, s se afle n diferite stri, s aib comportamente diferite. Polimorfismul
obiectual, care trebuie s fie abstract, se manifest n lucrul cu obiecte din clase aparinnd unei
ierarhii de clase, unde, prin redefinirea unor date sau metode, se obin membri diferii avnd ns
acelai 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 ntrziat. La limbajele cu legare timpurie, adresa la care se face un apel al unui
subprogram se stabilete la compilare. La limbajele cu legare ntrziat, aceast adres se
stabilete doar in momentul rulrii, putndu-se calcula distinct, n funcie 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 concepie, 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, aparinnd claselor derivate din PIESA,
referirea la metoda muta pare nedefinit. Totui mecanismele POO permit stabilirea, n momentul
apelului, a clasei proxime creia i aparine obiectul T i apelarea metodei corespunztore (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 funciei din clasa de baz, i corespunde un specificator override al


funciei din clasa derivat ce redefinete funcia din clasa de baz.
O metod ne-virtual nu este polimorfic i, indiferent de clasa creia i aparine obiectul, va
fi invocat metoda din clasa de baz.

I.3.6. Principiile programrii orientate pe obiecte


Ideea POO este de a crea programele ca o colecie de obiecte, uniti individuale de cod
care interacioneaz unele cu altele, n loc de simple liste de instruciuni sau de apeluri de
proceduri.
Obiectele POO sunt, de obicei, reprezentri ale obiectelor din viaa real (domeniul
problemei), astfel nct programele realizate prin tehnica POO sunt mai uor de neles, de
depanat i de extins dect programele procedurale. Aceasta este adevrat 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
abstractizrii, entitilor din domeniul problemei se definesc prin clase.
2. ncapsularea numit i ascunderea de informaii, 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. motenirea organizeaz i faciliteaz polimorfismul i ncapsularea permind definirea
si crearea unor clase specializate plecnd de la clase (generale) care sunt deja definite acestea pot mprti (i extinde) comportamentul lor fr a fi nevoie de redefinirea
aceluiai comportament.
4. Polimorfismul - posibilitatea mai multor obiecte dintr-o ierarhie de clase de a utiliza
denumiri de metode cu acelai nume dar, cu un comportament diferit.

I.4. Structura unei aplicaii orientat pe obiecte n C#


Limbajul C# permite utilizarea programrii orientate pe obiecte respectnd toate principiile
enunate anterior.
Toate componentele limbajului sunt ntr-un fel sau altul, asociate noiunii de clas. Programul
nsui este o clas avnd metoda static Main() ca punct de intrare, clas ce nu se instaniaz.

81

Chiar i tipurile predefinite byte, int sau bool sunt clase sigilate derivate din clasa ValueType din
spaiul System. Tot din ierarhia de clase oferit de limbaj se obin i tipuri speciale cum ar fi:
interfee, delegri i atribute. ncepnd cu versiunea 2.0 a limbajului i s-a adugat un nou tip:
clasele generice, echivalentul claselor template din C++.
n cele ce urmeaz vom analiza, fr a intra n detalii o aplicaie 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 cuvnt rezervat pentru noiunea de clas
Copil numele clasei

Copil

{ } corpul clasei
Dac considerm clasa Copil ca i clas de baz,

Fetita

putem deriva dou clase Fetia i Biat

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 cteva noiuni legate de constructorii unei clase:
Constructorul este o funcie care face parte din corpul unei clase. Corpul constructorului este format
din instruciuni care se execut la crearea unui nou obiect al clasei respective (sau la crearea clasei,
n cazul constructorilor cu modificatorul static).

pot exista mai muli constructori care se pot diferenia prin lista lor de parametri

constructorii nu pot fi motenii

dac o clas nu are definit niciun constructor, se va asigna automat constructorul fr


parametri al clasei de baz (clasa object, dac nu este precizat clasa de baz)
82

Instanierea presupune declararea unei variabile de tipul clasei respective i iniializarea acesteia
prin apelul constructorului clasei (unul dintre ei, dac sunt definii mai muli) precedat de operatorul
new.
Relum exemplu de mai sus n care vom prezenta un constructor fr parametri i
constructorul implicit din clasa derivat. Vom aduga un constructor fr parametri. La iniializarea
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
//constructorul fara parametrii ai clasei

public Copil ( )
{
nume = Console.ReadLine( );
}
}
class Fetita: Copil
{ }
...
Fetita f = new Fetita ( );
Copil c = new Copil ( );

I.4.3. Suprancrcarea constructorilor i definirea constructorilor n


clasele derivate
Relum exemplul anterior i l dezvoltm:

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 instruciuni care se execut la distrugerea unui obiect al
clasei respective. Pentru orice clas poate fi definit un singur constructor. Destructorii nu pot fi
motenii. 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 funcii: 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)
{
nume = s;
}
}
class Fetita : Copil
{
public Fetita(string s)
: base(s)
{
nume = "Fetita " + nume;
//din clasa de baza
}
}

//constructor cu parametru

//base semnifica faptul ca


//se face apel la
//constructorul

Fetita c = new Fetita();


Copil.adaug_copil(c);
//referina 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 afieaz o list cu numele celor 3 copii
...

Definirea datelor i metodelor nestatice corespunztoare 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. Proprieti
Proprietile sunt asemntoare cu metodele n ceea ce privete 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 amndou, n orice
ordine.
Este o manier de lucru recomandabil aceea de a proteja datele membru (cmpuri) ale
clasei, definind instrumente de acces la acestea: pentru a obine valoarea cmpului respectiv (get)
sau de a memora o anumit valoare n cmpul respectiv (set). Dac metoda de acces get este
perfect asimilabil cu o metod ce returneaz o valoare (valoarea datei pe care vrem s-o obinem
sau valoarea ei modificat conform unei prelucrri 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 funcie de context) valoarea respectiv cmpului. Cum parametrul
corespunztor valorii transmise nu apare n structura sintactic a metodei, este de tiut c el este
implicit identificat prin cuvntul value. Dac se supune unor condiii specifice problemei, se face o
atribuire de felul cmp=value.
Definirea n clasa Copil a proprietii Nume, corespunztoare cmpului protejat ce reine, sub
forma unui ir de caractere, numele copilului respectiv. Se va observ c proprietatea este
motenit i de clasele derivate Fetia i Biat.

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 prelucrrile care definesc comportarea sistemului. Obiectele sunt responsabile pentru
modificarea datelor proprii.
n proiectarea unei aplicaii POO parcurgem urmtoarele etape:
1. identificarea entitilor, adic a obiectelor care apar n domeniul aplicaiei, prin
evidenierea substantivelor din enunul problemei
2. pentru fiecare obiect se identific datele i operaiile, prin evidenierea verbelor i
adjectivelor care caracterizeaz subiectul respectiv
3. identificarea relaiilor dintre entiti
4. crearea unei ierarhii de clase, pornind de la aceste entiti
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 aplicaie C# este format din una sau mai multe clase, grupate n spaii de nume namespaces. n mod obligatoriu, doar una dintre aceste clase conine un punct de intrare - entry
point, i anume metoda Main.
Sintaxa:
[atribut][modificatorAcces] class
[identificator][:clasaBaza]
{
corpul_clasei
}

unde:
atribut este opional, reprezentnd informaii declarative cu privire la entitatea definit
modificatorAcces - este opional, iar n cazul n care lipsete se consider public
modificatorAcces
public

Explicaii
acces nelimitat, clasa este vizibil peste tot

internal

acces permis doar n clasa sau spaiul 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 semnificnd accesul n clasa care-l


conine sau n tipurile derivate din clasa care-l conine

new

permis claselor interioare. Clasa cu acest modificator ascunde un


membru cu acelai nume care este motenit

sealed

clasa nu poate fi motenit

abstract

clasa nu poate fi dect clas de baz, neputnd fi instaniat. Se


folosete pentru clase interioare sau spaii de nume

identificator - este numele clasei


88

clasaBaza - este opional, fiind numele clasei de baz, din care deriv clasa actual.

Exemplul 64: Se consider clasa IncludeClase care include ase clase avnd modificatori de
acces diferii. Se pune problema vizibilitii 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 alctuit din:

date

funcii

Att datele ct i funciile pot avea ca modificatori de acces:


modificatorAcces
public

Explicaii
Membrul este accesibil de oriunde

internal

Membrul este accesibil doar n assembly-ul curent (bloc


funcional al unei aplicaii .NET)

89

protected

Membrul este accesibil oricrui membru al clasei care-l conine i


a claselor derivate

private

Modificator implicit. Accesibil permis doar pentru clasa care-l


conine

protected internal

Membrul este accesibil oricrui membru al clasei care-l conine 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 opional. 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,

cmpuri.

Constantele - descriu valori fixe, putnd fi valori calculate sau dependente de alte
constante. n mod obligatoriu valoarea unei astfel de constante trebuie s fie calculat n momentul
compilrii. Valoarea unei constante se declar prin cuvntul 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;
}

Cmpul - reprezint o dat variabil a unei clase. n afar de modificatorii menionai mai
sus, se mai adaug: new, readonly, volatile, static. Opional, cmpurile pot fi iniializate cu valori
compatibile. Un astfel de cmp se poate folosi fie prin specificarea numelui su, 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;
}
}

Cmpuri de instan
n cazul n care ntr-o declaraie de cmp nu este inclus modificatorul static, atunci
respectivul cmp se va regsi n orice obiect de tipul clasei curente care va fi instaniat. Deoarece
un astfel de cmp are o valoare specific fiecrui obiect, accesarea lui se va face folosind numele
obiectului:
obiect.a = 1;

91

Un cmp special este this care reprezint o referin la obiectul curent

Cmpuri statice
Dac ntr-o declaraie de cmp apare specificatorul static, cmpul respectiv va aparine
clasei. Accesarea unui astfel de cmp 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++;
}
}

Cmpuri readonly
Pentru a declara un cmp readonly se va folosi cuvntul readonly n declaraia 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 compilrii valoarea cmpului readonly nu se presupune a fi cunoscut.

Cmpuri volatile
Cmpurile volatile se declar cu ajutorul cuvntului volatile, care poate fi ataat doar
urmtoarelor 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

Iniializarea cmpurilor
Valorile implicite pe care le iau cmpurile la declararea lor sunt:
tip
numeric
bool
char
enum
referin

valoare
0
false
\0
0
null

I.5.1.(2) Funcii
Funciile pot fi:

Constructori

Destructori

Metode

Proprieti

Evenimente

Indexatori

Operatori

I.5.1.(3)

Constructori

Definiie: Constructorii sunt funcii care folosesc la iniializarea unei instane a clasei.
Constructorii au acelai 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
instruciunilor care formeaz corpul constructorului curent. Iniializatorul poate lua dou forme:
base([parametri]) sau this([parametri]). Dac nu se precizeaz niciun iniializator,
implicit se va asocia base( ).
n cazul n care nu definim nici un constructor, C# va crea unul implicit avnd corpul vid.

Exemplul 69:
class Elev
{
public Elev()
{
}
}

//constructor

O clas poate conine mai muli constructori, difereniai dup numrul 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 instanierea 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();
}
}
}

Observaie: Constructorii nu pot fi motenii.

I.5.1.(4) Destructori
Destructorul clasei implementeaz aciunile necesare distrugerii unei instane 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 motenit.

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 aciune. Metoda poate admite
parametri i returna valori. Tipul returnat de ctre 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 (suprancrcate), adic se pot defini mai multe metode, care s
poarte acelai nume, dar s difere prin numrul i tipul de parametri. Valoarea returnat de ctre o
metod nu poate s fie luat n considerare n cazul supradefinirii.
Sintaxa este:
modificatorAcces tipReturnat numeMetoda([parametri])
[{
corp_Metoda
}]

unde:
modificatorAcces - este opional. n cazul n care lipsete 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 definete n mod explicit
un membru al unei interfee, numele este de forma:
[numeInterfata].[numeMetoda]

parametri - lista de parametri formali este o succesiune de declarri desprite prin virgule,
declararea unui parametru avnd sintaxa:

[atribut][modificator] tip nume

Modificatorul unui parametru poate fi ref (parametru de intrare i ieire) sau out (parametru
care este numai de ieire). 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 ;


Semntura fiecrei metode este format din numele metodei, modificatorii acesteia, numrul
i tipul parametrilor. Din semntur (amprent) nu fac parte tipul returnat, numele parametrilor
formali i nici specificatorii ref i out.

Numele metodei trebuie s difere de numele oricrui alt membru care nu este metod.
La apelul metodei, orice parametru trebuie s aib acelai 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. Proprieti
Proprietatea este un membru al clasei care ne permite s accedem sau s modificm
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 specificnd tipul folosit de accesorii get
(tipul valorii returnate) i set (tipul valorii atribuite).
Accesorul get corespunde unei metode fr parametri, care returneaz o valoare de tipul
proprietii.
Accesorul set corespunde unei metode cu un singur parametru, de tipul proprietii i tip de
retur void.
Dac proprietatea nu este abstract sau extern, poate s apar una singur dintre cele dou
metode de acces sau amndou, n orice ordine.
Este o manier de lucru recomandabil aceea de a proteja datele membru (cmpuri) ale
clasei, definind instrumente de acces la acestea: pentru a obine valoarea cmpului respectiv (get)
sau de a memora o anumit valoare n cmpul respectiv (set). Dac metoda de acces get este
perfect asimilabil cu o metod ce returneaz o valoare (valoarea datei pe care vrem s-o obinem
sau valoarea ei modificat conform unei prelucrri 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 funcie de context) valoarea respectiv cmpului. Cum parametrul
98

corespunztor valorii transmise nu apare n structura sintactic a metodei, este de tiut c el este
implicit identificat prin cuvntul 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 delegri

Evenimentele sunt membri ai unei clase ce permit clasei sau obiectelor clasei s fac
notificri, adic s anune celelalte obiecte asupra unor schimbri petrecute la nivelul strii lor.
Clasa furnizoare a unui eveniment public (pune la dispoziia altor clase) acest lucru printr-o
declarare event care asociaz evenimentului un delegat, adic o referin ctre o funcie
necunoscut creia i se precizeaz doar antetul, funcia urmnd 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 rspund 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 spaiul 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 tratrii evenimentelor
100

Exemplul 75: dorim s definim o metod asociat unui vector de numere ntregi, metod ce verific
dac vectorul este o succesiune cresctoare sau descresctoare. O implementare generic se
poate realiza folosind delegri:
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 ctre o
//funcie 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 aplicaiei. Se definete un tip
delegat TD (s zicem) cu nite 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 (iniial null). O clas C interesat s fie ntiinat cnd se face vreo
interschimbare ntr-un vector pentru a genera o animaie (de exemplu), va implementa o metod M
ce realizeaz animaia i va aduga pe M (prin intermediul unui delegat) la x.E+=new
[tip_delegat](M). Cumulnd mai multe astfel de referine, 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 adugate la E.

I.5.1.(6) Indexatori

Sunt cazuri n care are sens s tratm o clas ca un array. Cei care au studiat C++ vor
observa c este o generalizare a suprancrcrii operatorului [ ] din respectivul limbaj.
Sintaxa:
[atribut][modificatorIndexator] declaratorDeIndexator
{
declaratiiDeAccesor
}

unde:
modificatorIndexator poate fi new,

public,

protected,

virtual, sealed, override, abstract, extern.

102

internal,

private,

declaratorDeIndexator are forma:

tipReturnat this [listaParametrilorFormali]

unde:
listaParametrilorFormali trebuie s conin cel puin un parametru, parametru care nu trebuie s
fie de tipul ref sau out.

declaratiiDeAccesor asemntoare cu cele de la proprieti, trebuie s conin accesorul get


sau accesorul set.
Observaie: Indexatorii i proprietile sunt asemntoare n ceea ce privete utilizarea
accesorilor get i set. Un indexator poate fi privit ca o proprietate cu mai multe valori. Pe cnd o
proprietate poate fi declarat static, acest lucru este interzis n cazul indexatorilor.
Cnd folosim un indexator, sintaxa este asemntoare cu cea de la vectori. Totui exist
deosebiri:

indexatorii pot folosi indici nenumerici, pe cnd un vector trebuie s aib indicii de tip ntreg

indexatorii pot fi supradefinii, la fel ca metodele, pe cnd vectorii nu

indexatorii nu pot fi folosii ca parametrii ref sau out, pe cnd 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

Definiie: operatorul este un membru care definete semnificaia unei expresii operator care
poate fi aplicat unei instane a unei clase. Pentru cei care cunosc C++, operatorul corespunde
suprancrcrii din respectivul limbaj.
Sintaxa:
[atribut] modificatorOperator declaratieDeOprator corpOperator

Observaia 1: Operatorii trebuiesc declarai publici sau statici.


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

104

Observaia 3: n antetul unui operator nu poate aprea, de mai multe ori, acelai
modificator.
Se pot declara operatori: unari, binari i de conversie.
Operatori unari
Suprancrcarea operatorilor unari are urmtoarea sintax:
tip operatorUnarSuprancrcabil (tip identificator) corp

Operatorii unari suprancrcabili sunt: + - ! ++ true false.


Reguli pentru suprancrcarea operatorilor unari:
Fie T clasa care conine definiia 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 definii pentru a prevenii o
eroare de compilare.
Exemplul 77:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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
Suprancrcarea operatorilor binari are urmtoarea sintax:
tip operator operatorBinarSuprancrcabil (tip identificator,
tip identificator) corp

Operatorii binari suprancrcabili sunt: + - * / & | ^ << >> == != > < >= <=
Reguli pentru suprancrcarea operatorilor binari:
1. Cel puin 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. Urmtorii operatori trebuie s se declare n pereche:
a. operatorii == i !=
b. operatorii > i <
c. operatorii >= i <=
Exemplul 78:

106

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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:

implicii se efectueaz de la un tip mai mic la un tip mai mare i reuesc ntotdeauna,
nepierzndu-se date

explicii se efectueaz prin intermediul expresiilor de conversie, putndu-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 destinaie (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
using
using
using

System;
System.Collections.Generic;
System.Linq;
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
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 funcii generice

Definiie: 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 funcionaliti 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 obinuit a unei clase, este prezena caracterelor
< i >, care permit definirea tipului pe care stiva l va avea, ca i cum ar fi un parametru al clasei.
La instanierea clasei trebuie s declarm tipul datelor utilizate.
Tipurile generice (parametrizate) permit construirea de clase, structuri, interfee, delegai sau
metode care sunt parametrizate printr-un tip pe care l pot stoca sau manipula.

Exemplul 81: S considerm 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 interfeelor

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 implementm o clas Stiva care s permit adugarea i extragerea de

elemente. Pentru a simplifica problema, vom considera c stiva nu poate conine dect un anumit
numr de elemente, ceea ce ne va permite s utilizm tablouri n C#.
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 cteva probleme:

elementele clasei Stiva trebuie s fie convertite explicit

atunci cnd se folosete clasa Stiva cu elemente

de tip valoare, se realizeaz implicit o

operaie de boxing cu inserarea unui element i o operaie 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 execuie
Deoarece problema conversiei nu este detectat la compilare, va produce o excepie la

execuie. 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 poriuni
din cod. Acest lucru se va rezolva cu ajutorul tipurilor generice.
C# ne permite rezolvarea unor astfel de probleme introducnd tipurile generice. Concret
putem implementa o list de elemente de tip T, lsnd libertatea utilizatorului s specifice tipul T la
instanierea clasei.

113

Exemplul 85:

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 (motenire)

I.7.1.

Principiile motenirii

Prin utilizarea motenirii se poate defini o clas general care definete trsturi comune la
un ansamblu de obiecte. Aceast clas poate fi motenit de ctre alte clase specifice, fiecare
dintre acestea adugnd elemente care-i sunt unice ei.

114

O clas care este motenit se numete clas de baz sau superclas, iar o clas care o
motenete pe aceasta se numete 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 motenete 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 rndul ei s fie clas de baz pentru o alt clas. n acest fel se
poate defini noiunea de ierarhie de clase.
Limbajul C#, spre deosebire de C++, admite doar motenirea simpl, n sensul c
derivarea se admite doar dintr-o clas de baz, fiind permis doar derivarea public
n contextul mecanismelor de motenire trebuie amintii modificatorii abstract i sealed aplicai
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 obine obiecte prin operaia
de instaniere, 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 urmnd 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 motenii

Deseori, n procesul derivrii, avem nevoie de acces la membrii motenii 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 cuvntului cheie protected


Cuvntul cheie protected permite restrngerea accesului unui membru al clasei de baz
doar la clasele sale derivate. Membrii protejai motenii devin n mod automat protejai.

I.7.3. Apelul constructorilor clasei de baz


Exemplul 88:
117

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

//constructor

clasa Derivata : ClasaDeBaza


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

I.7.3.

Metode

Prin mecanismul de motenire avem posibilitatea reutilizrii 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 aceeai signatur (nume, modificator de acces, tip returnat i parametri).
Pentru declararea unei metode ca fiind virtual se folosete cuvntul cheie virtual. n clasele
derivate se va folosi cuvntul 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 specificm c metoda
clasei derivate este o implementare nou a respectivei metode. Pentru aceasta vom folosi new cu
semnificaia c metoda are aceeai signatur cu a celei din clasa de baz, dar dorim s mascm
definirea ei n clasa de baz.
Exemplul 90:

class ClasaDeBaza
{
public virtual void Metoda()
{
...
}
}
class Derivata : ClasaDeBaza
{
public new void Metoda()
{
...
}
}

I.7.4.

Interfee

Interfeele sunt foarte importante n programarea orientat pe obiecte, deoarece permit


utilizarea polimorfismului ntr-un sens mai extins.
Definiie: O interfa este o component a aplicaiei, asemntoare unei clase, care declar
prin membrii si (metode, proprieti, evenimente i indexatori) un comportament unitar aplicabil
mai multor clase, comportament care nu se poate defini prin ierarhia de clase a aplicaiei.
De exemplu, dac vom considera arborele din figura urmtoare, n care AVERE este o clas
abstract, iar derivarea claselor a fost conceput urmrind proprietile comune ale componentelor
119

unei averi, atunci o clas VENIT nu este posibil, deoarece ea ar moteni de la toate clasele
evideniate, iar motenirea multipl nu este admis n C#.

AVERE
Proprietate
Imobiliara

Bani
Bun

Teren

Depunere

Credit_primit

Investiie

B_inchiriat

Actiune

Productiv

Mobilier

Cot

Neproductiv

Altul

Credit_acordat

VENIT

Imobil

(din produse, din


chirii, din dobnzi,
dividende)
calc()

De_folosin
I_inchiriat

Pentru metodele din cadrul unei interfee nu se d nici o implementare, ci sunt pur i simplu
specificate, implementarea lor fiind furnizat de unele dintre clasele aplicaiei. Acele clase care
ader la o interfa spunem c implementeaz interfaa respectiv. Nu exist instaniere n
cazul interfeelor, dar se admit derivri, inclusiv moteniri multiple.
n exemplul nostru, se poate defini o interfa VENIT care s conin antetul unei metode
calc (s zicem) pentru calculul venitului obinut, fiecare dintre clasele care implementeaz interfaa
VENIT fiind obligat s furnizeze o implementare (dup o formul de calcul specific) pentru
metoda calc din interfa. Orice clas care dorete s adere la interfa trebuie s implementeze
toate metodele din interfa. Toate clasele care motenesc dintr-o clas care implementeaz o
interfa motenesc, evident, metodele respective, dar le pot i redefini (de exemplu, clasa
Credit_acordat redefinete metoda calc din clasa Investiie, deoarece formula de calcul
implementat acolo nu i se potrivete i ei. Dac n sens polimorfic spunem c Investiie este i
de tip Bani i de tip Avere, tot aa putem spune c o clas care implementeaz interfaa VENIT
i clasele derivate din ea sunt i de tip VENIT).
De exemplu, dac presupunem c toate clasele subliniate implementeaz interfaa
VENIT, atunci pentru o avere cu aciuni 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 excepiilor n C#

Definiie: O excepie este un obiect care ncapsuleaz informaii despre o situaie anormal.
Excepia se folosete pentru a semnala contextul n care apare acea situaie deosebit
Observaie: Nu trebuie confundat termenul de excepie cu cel de eroare sau bug.
Excepiile nu sunt concepute pentru prevenirea bug-urilor. Chiar dac programatorul elimin toate
bug-urile din programul su pot aprea erori pe care el nu le poate preveni:

ncercare de deschidere a unui fiier inexistent

mpriri la zero

etc.

n cazul n care o metod ntlnete o astfel de excepie, atunci respectiva excepie va


trebui prins n vederea tratrii (rezolvrii) ei.
n C# se pot arunca ca excepii obiecte de tip System.Exception sau derivate ale lui. Pe
lng ierarhia de excepii pe care limbajul C# o are inclus, programatorul i poate crea propriile
sale tipuri excepie.
Exception

SystemException

OutOfMemoryException

IOException

NullReferenceException

AplicationException

Ierarhia excepiilor
121

Dintre metodele i proprietile clasei Exception amintim:


Metodele i proprietile clasei Exception
public Exception( )
public Exception (string)
public Exception (string, Exception)

public virtual string HelpLink {get; set}

public Exception InnerException {get;}


public virtual string Message {get;}
public virtual string Source {get; set;}

public virtual string StackTrace {get;}

public MethodBase TargetSite {get;}

Explicaii
sunt constructori

observm c o excep ie poate


conine n interiorul s o instan a
unei alte excepii
obine sau seteaz o legtur ctre
fiierul Help asociat excepiei, sau
ctre o adres Web
returneaz excepia care este
ncorporat n excepia curent
obine un mesaj care descrie excepia
curent
obine sau seteaz numele aplicaiei
sau al obiectului care a cauzat
eroarea
obine o reprezentare de tip string a
apelurilor de metode care au dus la
apariia excepiei
obine metoda care a aruncat
excepia curent

C# definete cteva excepii standard derivate din System.Exception. Acestea sunt generate
cnd se produc erori la execu ia programului. Dintre acestea amintim:
Excepia

Explicaii
Incompatibilitate ntre tipul valorii
memorate i tipul tabloului
ncercare de mprire la zero

ArrayTypeMismatchException
DivideByZeroException
IndexOutOfRangeException

Indexul tabloului depete marginile


definite
Operatorul cast incorect la execuie

InvalidCastException
OutOfMemoryException
OverflowException

Datorit memoriei insuficiente apelul


lui new eueaz
Depire aritmetic

StackOverflowException

Depirea capacitii (definite) stivei

Observaie: Este posibil definirea de ctre programator a propriilor clase de excepii.


Acestea vor fi derivate din ApplicationException.

122

I.8.1.

Aruncarea i prinderea excepiilor

I.8.1.(1) Blocurile try i catch


POO ofer o soluie pentru gestionarea erorilor: folosirea blocurilor try i catch.

scrierea codului, programatorul va separa acele instruciuni care sunt sigure (adic nu pot fi
generatoare de excepii), de cele care sunt susceptibile s conduc la erori. Partea de program
care poate genera excepii o vom plasa ntr-un bloc try, iar partea corespunztoare tratrii
excepiei, ntr-un bloc catch.
n cazul n care blocul try genereaz o excepie, Runtime ntrerupe execuia i caut un bloc
catch apropiat care, n funcie de tipul su s poat trata respectiva eroare. n cazul n care este
gsit respectivul bloc catch programul continu cu instruciunile din corpul catch. n cazul n care
nu se gsete nici un catch corespunztor, execuia programului este ntrerupt.
Avnd n vedere c ntr-un corp try pot s apar excepii diferite, n program pot exista mai
multe blocuri corespunztoare catch.

Exemplul 91:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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");
//Console.WriteLine(e);
}

123

//(1)
//(2)

/*
catch (DivideByZeroException e)
{
//Console.WriteLine(e);
//(3)
Console.WriteLine("Exceptia DivideByZero");
//(4)
}*/
Console.WriteLine("Programul ruleaza in continuare");//(5)

S analizm puin programul de mai sus:

Dac liniile (2) i (3) nu sunt comentate, n urma execuii programului, respectivele linii afieaz
informaii despre excepiile aprute.

Liniile (1) i (4) au fost puse pentru a personaliza informaiile referitoare la excepiile aprute.

Linia (5) a fost pus n program pentru a demonstra rularea fr probleme, n cazul n care
blocurile catch exist. ncercai s comentai unul dintre blocurile catch, introducei date care
s produc excepia pe care blocul comentat ar trata-o i vei observa ntreruperea, cu mesaj
de eroare a rulrii programului.
Observaie: Pentru a intercepta orice excepii, indiferent de tipul lor se va folosi catch fr

parametru. Prin aceasta se va crea o rutin care va intercepta i trata toate excepiile.

I.8.1.(2) Instruciunea throw


Programatorul poate s-i compun modaliti proprii de aruncare a erorilor folosind
instruciunea throw:
throw new NumeExceptie(exceptie);
unde:
NumeExceptie trebuie s fie numele unei clase apropiate de excepia avut n vedere
excepie este un mesaj care apare n cazul n care apare excepia, 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 analizm programul de mai sus:

Dac comentm liniile (1), (2), (3), (4), (5), (6), (7) i la rularea programului introducem un
numr n loc de o cifr, programul se oprete din execuie, 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 ateapt un bloc catch sau finally

Dac nici una dintre liniile programului nu este comentat, la rulare, chiar dac introduce un
numr n loc de o cifr vom obine:

125

I.8.1.(3) Blocul finally


Limbajul C# permite ca la ieirea dintr-un bloc try s fie executate obligatoriu, n cazul n
care programatorul dorete acest lucru, anumite instruciuni. Pentru acest lucru, respectivele
instruciuni vor fi plasate ntr-un bloc finally.
Blocul finally este util fie pentru a evita scrierea unor instruciuni de mai multe ori, fie
pentru a elibera resursele dup prsirea excepiei.

I.9.

Polimorfism
I.9.1.

Introducere

n Capitolul 3 defineam noiunea de polimorfism, folosind o extensie a sensului etimologic:


un obiect polimorfic este cel capabil s ia diferite forme, s se afle n diferite stri, s aib
comportamente diferite. Polimorfismul obiectual, care trebuie s fie abstract, se manifest n
lucrul cu obiecte din clase aparinnd unei ierarhii de clase, unde, prin redefinirea unor date sau
metode, se obin membri diferii avnd ns acelai 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 funciei din clasa de baz, i corespunde un specificator override al
funciei din clasa derivat ce redefinete funcia din clasa de baz.
O metod ne-virtual nu este polimorfic i, indiferent de clasa creia i aparine obiectul, va
fi invocat metoda din clasa de baz.
126

Limbajul C# admite trei tipuri de polimorfism:

polimorfism parametric

polimorfism ad-hoc

polimorfism de motenire

I.9.2.

Polimorfismul parametric

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


aceast form de polimorfism, o funcie va prelucra orice numr de parametri. Pentru aceasta se
va folosi un parametru de tip params.
Exemplul 93: S considerm o funcie F cu un parametru formal, de tip vector, declarat folosind
modificatorul params. Acest lucru va permite folosirea mai multor parametri actuali, la apelul
funciei, prin intermediul acelui singur parametru formal.

using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 numete i suprancrcarea metodelor. Prin acest mecanism
se pot defini n cadrul unei clase mai multe metode, toate avnd acelai nume, dar cu tipul i
numrul de parametri diferii. La compilare, n funcie de parametri folosii la apel, se va apela o
funcie sau alta.
Exemplul 94:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 motenire

n cazul acestui tip de motenire vom discuta ntr-o ierarhie de clase. n acest caz ne
punem problema apelrii metodelor, avnd aceeai list de parametri formali, metode ce
fac parte din clase diferite.
Exemplul 95:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 discutm despre prima linie afiat (cea de-a doua este evident). Apelul lui Afis() se
rezolv n momentul compilrii 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 instaniat pe baza unui obiect
din clasa Derivata.

I.9.5.

Modificatorii virtual i override

n cazul n care se dorete ca apelul metodelor s se fac la rulare i nu la compilare vom


reconsidera exemplul anterior n care funcia Afis( ) din clasa de baz o declarm virtual, iar
funcia Afis( ) din clasa derivat o considerm ca suprascriere a lui Afis( ) din clasa de baz:
Exemplul 96:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 dorete ca o metod dintr-o clas derivat s aib aceeai semntur cu
o metod dintr-o clas de baz, dar s nu fie considerat o suprascriere a ei, vom folosi
modificatorul new.
Exemplul 97:
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
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 avnd 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
}
}
class Derivata : Baza
{
sealed override public void Afis()
{
Console.WriteLine("Apelul functiei Afis din
}
}
class Derivata2 : Derivata
{
override public void Afis()
//!!! EROARE
{
Console.WriteLine("Apelul functiei Afis din
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = new Derivata();
Derivata2 obiect3 = new Derivata2();
obiect1.Afis();
obiect2.Afis();
obiect3.Afis();
}
}
}
132

clasa de baza\n");

clasa derivata\n");

!!!
clasa Derivata2\n");

//(1)
//(2)

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 programrii 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 secvene de program, secvene care,
mpreun cu secvenele scrise textual vor forma programul.
Spunem c o aplicaie este vizual dac dispune de o interfa grafic sugestiv i pune la
dispoziia utilizatorului instrumente specifice de utilizare (drag, clic, hint etc.)
Realizarea unei aplicaii 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 aplicaiei mai trebuie respectate i principiile proiectrii interfeelor:

Simplitatea: Interfaa trebuie s fie ct mai uor de neles i de nvat de ctre utilizator
i s permit acestuia s efectueze operaiile dorite n timp ct mai scurt. n acest sens,
este vital culegerea de informaii despre utilizatorii finali ai aplicaiei i a modului n care
acetia sunt obinuii s lucreze.

Poziia controalelor: Locaia controalelor dintr-o fereastr trebuie s reflecte importana


relativ i frecvena de utilizare. Astfel, cnd un utilizator trebuie s introduc nite
informaii unele obligatorii i altele opionale este indicat s organizm controalele
astfel nct primele s fie cele care preiau informaii obligatorii.

Consistena: Ferestrele i controalele trebuie s fie afiate dup un design asemntor


(template) pe parcursul utilizrii aplicaiei. nainte de a implementa interfaa, trebuie
decidem cum va arta aceasta, s definim template-ul.

Estetica: Interfaa trebuie s fie pe ct posibil plcut i atrgtoare.

133

II.2.

Mediul de dezvoltare Visual C# (prezentarea interfeei)

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


proiectare, ceea ce permite crearea aplicaiilor n mod interactiv, rapid i uor.
Pentru a construi o aplicaie Windows (FileNew Project) se selecteaz ca template
Windows Forms Application.

O aplicaie Windows conine cel puin o fereastr (Form) n care se poate crea o interfa cu
utilizatorul aplicaiei.
Componentele vizuale ale aplicaiei pot fi prelucrate n modul Designer (Shift+F7) pentru a
plasa noi obiecte, a le stabili proprietile etc. Codul din spatele unei componente vizuale este
accesibil n modul Code (F7).
n fereastra Solution Explorer sunt afiate toate fiierele pe care Microsoft Visual C# 2008
Express Edition le-a inclus n proiect. Form1.cs este formularul creat implicit ca parte a proiectului.
Fiierul Form1.cs conine 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 cnd este atins cu mouse-ul.
Fiierul Form1.cs poate fi vzut ca fiier text surs prin selectarea lui n fereastra Solution
Explorer, clic dreapta cu mouse-ul i selecia opiunii View Code.
Fereastra Properties (Ctrl+W,P) este utilizat pentru a schimba proprietile obiectelor.
Toolbox (Ctrl+W,X) conine controale standard drag-and-drop i componente utilizate n
crearea aplicaiei Windows. Controalele sunt grupate n categoriile logice din imaginea alturat.
Ferestrele care sunt afiate in fereastra principal se pot stabili prin selecie din meniul View.

La crearea unei noi aplicaii vizuale, Microsoft Visual C# 2008 Express Edition genereaz un
spaiu de nume care conine clasa static Program, cu metoda static ce constituie punctul de
intrare (de lansare) a aplicaiei:
static void Main()
{

...
Application.Run(new Form1());

Clasa Application este responsabil cu administrarea unei aplicaii Windows, punnd la


dispoziie proprieti pentru a obine informaii despre aplicaie, metode de lucru cu aplicaia i
altele. Toate metodele i proprietile clasei Application sunt statice. Metoda Run creeaz un
formular implicit, aplicaia rspunznd la mesajele utilizatorului pn cnd formularul va fi nchis.
Compilarea modulelor aplicaiei i asamblarea lor ntr-un singur fiier executabil se
realizeaz cu ajutorul opiunilor din meniul Build, uzual fiind Build Solution (F6).
135

Odat implementat, aplicaia poate fi lansat, cu asisten de depanare sau nu (opiunile


Start din meniul Debug). Alte faciliti de depanare pot fi folosite prin umrirea pas cu pas,
urmrirea pn la puncte de ntrerupere etc. (celelalte opiuni ale meniului Debug).
Ferestre auxiliare de urmrire 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 insernd controale selectate din fereastra de
instrumente (Toolbox) i setnd proprietile acestora.

II.3.

Elementele POO n context vizual

n cele ce urmeaz pentru explicaiile care vor avea loc vom considera o aplicaie Windows
numit Test:

n urma generrii proiectului Test avem:

136

Fereastra Toolbox

Fereastra Windows Forms


Designer n care s-a creat
Form1

Fereastra Properties

Fereastra pentru
afiarearea Listei de
erori
Bara de unelte

Fereastra Solution
Explorer

Bara de meniuri

Toate ferestrele, au n partea dreapt o piunez, care, dac este n poziie vertical
fixez fereastra deschis. n caz contrar

fereastra se nchide, retrgndu-se n partea dreapt

sau stng a mediului de programare.


Orice fereastr poate fi aranjat ntr-o poziie dorit de utilizator. Pentru aceasta dm clic
pe una dintre barele de titlu ale ferestrelor menionale mai sus (Solution Explorer, Properties,
Toolbox sau Error List) si o deplasm n poziia dorit. n acest proces vei fi ghidat de sgeile
137

care apar central i pe margini. De preferat ar fi ca aceste ferestre s rmn n poziiile lor
implicite.

Barele de instrumente
Implicit, la crearea unui proiect windows, apar dou bare de instrumente
Prima bar de unelte

unde:
Icoana

Semnificaie
proiect nou (Ctrl+Shift+A)

138

Icoana

Semnificaie

adugare de noi itemi (Ctrl+Shift+A)


deschide fiier (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

cutare i nlocuire (Ctrl + Shift + F)


139

Icoana

Semnificaie
fereastra pentru cutare
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 folosete atunci cnd dorim s acionm asupra mai multor
controale din fereastra noastr, i anume pentru: alinieri, spaieri, redimensionri, aducerea n
fa/spate a unora dintre controalele existente. Icoanele aflate pe aceast bar sunt deosebit de
sugestive pentru aciunea pe care o realizeaz.

Fereastra Toolbox
Revenind

la

fereastra

Toolbox.

Putem

deschidem una dintre opiunile din fereastr apsnd


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 msur, 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 dm 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 opiunea Open i va reaprea n
fereastra central. Dac dorim s vedem codul,
apsm pe opiunea View Code, iar n fereastra
principal

se

va

deschide,

nc

ferestr

corespunztoare codului dorit.


Acelai

lucru

putem

spune

despre

Properties.cs, din aceeai fereastr.


n toate cazurile menionate mai sus, pentru a
obine efectul afiat i n imagini, se va aciona
butonul din dreapta al mouse-ului.
Despre opiunile care apar n cazul n care dm
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 aplicaie.
Cele

mai

multe

controale

System.Windows.Forms.Control.

sunt

Datorit

obiecte
acestui
141

de
fapt

clase
multe

derivate
dintre

din

clasa

proprietile

evenimentele diverselor controale vor fi identice. Vom vedea, n aplicaiile care urmeaz, c exit
clase care definesc controale i care pot fi clase de baz pentru alte controale.
Fereastra Properties, din interfaa mediului de programare, vom observa c va conine
att proprietile ct i evenimentele ataate controalelor.

Proprietile controalelor, sunt

motenite sau supranscrise din clasa de baz Control. Tabelul de mai jos prezint proprietile
comune controalelor, proprieti furnizate de ctre clasa Control:
Proprietatea
Anchor
BackColor
Bottom
Dock
Enabled
ForeColor
Height
Left
Name
Parent
Right
TabIndex
TabStop
Tag
Top
Visible
Width

Descrierea proprietii
se refer la posibilitatea de a ancora controlul fa de o margine (sau
toate)
permite stabilirea culorii de fundal a controlului
permite stabilirea distanei dintre marginea de sus a ferestrei i control
ataeaz controlul la una dintre marginile ferestrei
permite controlului s recepioneze evenimente de la utilizator
permite stabilirea culorii textului
permite definirea nlimii controlului
permite stabilirea distanei dintre marginea din stnga a ferestrei i
marginea stnga a controlului
permite denumirea controlului pentru a-l putea mai uor vizualiza i
manipula n codul surs
printele controlului
permite stabilirea distanei dintre marginea din dreapta a ferestrei i
marginea din dreapta a controlului
prin numrul de ordine care i se ataeaz se stabilete ordinea activrii
controlului la apsarea tastei TAB
permite sau nu ca respectivul control s fie activat prin apsarea tastei
TAB
se refer la un ir de caractere pe care controlul l poate stoca n interiorul
su
permite stabilirea distanei dintre marginea de sus a ferestrei i marginea
de sus a controlului
stabilete dac respectivul control, care exit n fereastr, este (TRUE)
sau nu vizibil
stabilete limea controlului

Aplicaiile pe care le crem trebuie s fie capabile, prin intermediul controalelor, s


sesizeze aciunea utilizatorului asupra respectivelor controale.

n funcie de tipul aciunii vor

reaciona, printr-o secven de cod sau alta. Tot clasa Control amintit mai sus, implementeaz
i o serie de evenimente la care controalele vor reaciona:

Evenimentul
Clic
DoubleClic
DragDrop

Descrierea evenimentului
se genereaz cnd se d clic asupra unui control
se genereaz cnd se d dublu clic asupra unui control. Excepie fcnd
Button asupra cruia nu se va putea face dublu clic, deoarece controlul
acioneaz la primul clic
se genereazla finalizarea lui drag and drop
142

Evenimentul
DragEnter

Descrierea evenimentului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge n
interiorul controlului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge s
prseasc controlului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge
deasupra controlului
se genereaz atunci cnd o tast este apsat n timp ce controlul este
activ. Se va furniza codul ASCII al tastei apsate. Se genereaz nainte
de evenimentele KeyPress i KeyUp
se genereaz atunci cnd o tast este apsat n timp ce controlul este
activ. Se va furniza codul de scanare al tastei apsate. Se genereaz
dup KeyDown i nainte de KeyUp
se genereaz cnd o tast este eliberat n timp ce controlul este activ.
Se genereaz dup KeyDown i KeyPress
se genereaz cnd controlul devine activ (se mai spune: cnd controlul
primete input focusul)
se genereaz cnd controlul devine inactiv (se mai spune: cnd controlul
pierde input focusul)
se genereaz cnd cursorul mouse-ului este deasupra controlului i se
apas un buton al mouse-ului
se genereaz cnd trecem cu mouse-ul deasupra controlului
se geereaz cnd mouse-ul este deasupra controlului i eliberm un
buton al mouse-ului
se genereaz la desenarea controlului
se genereaz cnd un control este pe cale s devin activ. Se genereaz
dup terminarea evenimentului Validating, indicnd faptul c validarea
controlului este complet
se genereaz cnd un control este pe cale s devin activ

DragLeave
DragOver
KeyDown
KeyPress
KeyUp
GotFocus
LostFocus
MouseDown
MouseMove
MouseUp
Paint
Validated
Validating

II.4.

Construirea interfeei utilizator

II.4.1.

Ferestre

Spaiul 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 msur ce noi
desemnm componentele i comportamentul acesteia. n fapt, acest cod realizeaz: derivarea
unei clase proprii din System.Windows.Forms.Form, clas care este nzestrat cu o colecie de
controale (iniial vid). Constructorul ferestrei realizeaz instanieri ale claselor Button, MenuStrip,
Timer etc. (orice plasm noi n fereastr) i adaug referinele acestor obiecte la colecia de
controale ale ferestrei.
143

Dac modelul de fereastr reprezint ferestra principal a aplicaiei, atunci ea este


instaniat automat n programul principal (metoda Main). Dac nu, trebuie s scriem noi codul
care realizeaz instanierea.

Clasele derivate din Form motenesc o serie de proprieti 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


permind 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 deinut. Activarea


propietarului unui formular deschis modal va determina activarea formularului deschis modal. Cnd
un nou formular este activat folosind form.Show() nu va avea nici un deintor, acesta stabilinduse 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. Deintorul se poate stabili
setnd proprietarul nainte s apelm Form.ShowDialog() sau apelnd 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 proprieti ale form-urilor, reamintim:

StartPosition determin poziia ferestrei atunci cnd aceasta apare prima dat. Poziia poate fi
setat Manual, sau poate fi

centrat pe desktop (CenterScreen), stabilit de Windows,

formularul avnd dimensiunile i locaia stabilite de programator (WindowsDefaultLocation)


sau

Windows-ul

va

stabili

dimensiunea

iniial

locaia

pentru

formular

(WindowsDefaultBounds) sau, centrat pe formularul care l-a afiat (CenterParent) atunci


cnd formularul va fi afiat modal.

Location (X,Y) reprezint coordonatele colului din stnga sus al formularului relativ la colul
stnga sus al containerului. (Aceast propietate e ignorat dac StartPosition = Manual).

Micarea formularului ( i implicit schimbarea locaiei) poate fi tratat n evenimentele Move i


LocationChanged .
Locaia 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. Cnd se schimb propietile 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 coninut al su. 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 restriciona 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 conine sau nu un icon, butonul de nchidere al ferestrei
i meniul System (Restore,Move,Size,Maximize,Minimize,Close).

HelpButton-precizeaz dac butonul

va aprea sau nu lng butonul de nchidere al

formularului (doar dac MaximizeBox=false, MinimizeBox=false). Dac utilizatorul apas acest


buton i apoi apas oriunde pe formular va aprea 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 cnd formularul este
minimizat.

SizeGripStyle specific tipul pentru Size Grip (Auto, Show, Hide). Size grip

(n colul din

dreapta jos) indic faptul c aceast fereastr poate fi redimensionat.

TopMost precizeaz dac fereastra este afisat n faa tuturor celorlalte ferestre.

TransparencyKey identific o culoare care va deveni transparent pe form.


Definirea unei funcii 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 funcia de tratare, ci efectum dublu clic n csua
respectiv, se genereaz automat un nume pentru aceast funcie, innd cont de numele
controlului i de numele evenimentului (de exemplu button1_Click).
Dac n Designer efectum dublu clic pe un control, se va genera automat o funcie 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 numr :

Load apare cnd formularul este pentru prima data ncrcat n memorie.

FormClosed apare cnd formularul este nchis.

FormClosing apare cnd formularul se va inchide ca rezultat al aciunii utilizatorului asupra


butonului Close (Dac se seteaz CancelEventArgs.Cancel =True atunci se va opri nchiderea
formularului).

Activated apare pentru formularul activ.

Deactivate apare atunci cnd utilizatorul va da clic pe alt formular al aplicatiei.

II.4.2.

Controale

Unitatea de baz a unei interfee Windows o reprezint un control. Acesta poate fi gzduit
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 pri 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 su este de a gzdui alte controale.
Folosind proprietile, metodele i evenimentele unui formular, putem personaliza programul
nostru.
n tabelul de mai jos vei gsi o list cu controalele cel mai des folosite i cu descrierea lor.
Exemple de folosire a acestor controale vor urma dup explicarea proprietilor comune al
controalelor i formularelor.

Funcia
controlului
buton

Numele
controlului
Button

calendar

MonthCalendar

caset de
validare
etichet

CheckBox

caset cu
list
imagine

ListBox

pointer

Pointer

buton radio

RadioButton

Label

PictureBox

caset de text TextBox

II.5.

Descriere
Sunt folosite pentru a executa o secven de instruciuni n
momentul activrii lor de ctre utilizator
Afieaz implicit un mic calendar al lunii curente. Acesta
poate fi derulat i nainte i napoi la celelalte luni
calendaristice.
Ofer utilizatorului opiunile : da/nu sau include/exclude
Sunt folosite pentru afiarea etichetelor de text, i a pentru a
eticheta controalele.
Afieaz o list de articole din care utilizatorul poate alege.
Este folosit pentru adugarea imaginilor sau a altor resurse
de tip bitmap.
Este utilizat pentru selectarea, mutarea sau redimensionarea
unui control.
Este folosit pentru ca utilizatorul s selecteze un singur
element dint-un grup de selecii.
Este utilizat pentru afiarea textului generat de o aplicaie
sau pentru a primi datele introduse de la tastatur de ctre
utilizator.

Aplicaii

II.5.1.

Numere pare

Acest exemplu afieaz numerele pare din intervalul [0,n) unde n este o variabil global a
crei valoare este introdus de la tastatur. Se deschide o aplicaie Windows Forms pe care o vei
denumi Numere pare. Din fereastra Properties modificai numele formularului. Stabilii dimensiunea
formularului i culoarea de fond alegnd una dintre cele predefinite din opiunea BackColor.
Cu ajutorul metodei Drag and drop plasai pe formular un buton pe care vei introduce textul
START, dou controale TextBox, dou controale label pe care vei introduce textele din exemplul
de mai jos

147

Executai dublu clic pe butonul START i editai 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 executai dublu clic pe Form1.Designer.cs pentru a declara


variabilele globale n i i, n zona de declaraii a funciei 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 aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.

148

II.5.2.

Proprieti comune ale controalelor i formularelor:

Proprietatea Text Aceast proprietate poate fi setat n timpul proiectrii din fereastra
Properties, sau programatic, introducnd o declaraie n codul programului.

public Form1(){
InitializeComponent();
this.Text = "Primul formular";
}

Proprietile ForeColor i BackColor. Prima proprietate enunat seteaz culoare textului din
formular, iar cea de a doua seteaz culoarea formularului. Toate acestea le putei modifica
dup preferine din fereastra Properties.

Proprietatea BorderStyle. Controleaz stilul bordurii unui formular. ncercai s vedei cum se
modific setnd proprietatea la Fixed3D (tot din fereastra Properties).

Proprietatea FormatString v permite s setai un format comun de afiare pentru toate


obiectele din cadrul unei ListBox. Aceasta se gsete 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 tragei un TextBox ntr-un formular i modificai
valoarea proprietii Multiline din panoul Properties de la False la true.

Proprietatea AutoCheck cnd 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 coninutul.
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 aezate pe suprafaa controlului.

Proprietatea TabIndex seteaz sau returneaz poziia controlului n cadrul aranjrii taburilor.

Proprietatea Visible seteaz vizibilitatea controlului.

Proprietatea Width and Height permite setarea nlimii i a limii controlului.

II.5.3.

Metode i evenimente

Un eveniment este un mesaj trimis de un obiect atunci cnd are loc o anumit aciune.
Aceast actiune poate fi: interaciunea cu utilizatorul (mouse click) sau interaciunea cu alte entiti
de program. Un eveniment (event) poate fi apsarea unui buton, o selecie 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 proprieti ale clasei care le public. Cuvantul-cheie
event contoleaz cum sunt accesate aceste proprieti.

Metodele Show() i Close(). Evenimentul Click


Cnd dezvoltm programe pentru Windows, uneori trebuie s afim ferestre adiionale. De
asemenea trebuie s le facem s dispar de pe ecran. Pentru a reui acest lucru folosim
metodele Show() i Close() ale controlului. Cel mai important eveniment pentru Button este
Clic (desemnnd aciunea clic stnga pe buton).

Exemplul 2: Deschidere i nchidere de formulare


Deschidei o nou aplicaie Windows Forms, tragei un control de tip Button pe formular.
Din meniul Project selectai Add Windows Form, iar n caseta de dialog care apare adugai
numele Form2, pentru noul formular creat. n acest moment ai inclus n program dou formulare.
Tragei un buton n Form2 i executai dublu clic pe buton, pentru a afia administratorul su de
evenimente. Introducei acum n el linia de cod this.Close();.

private void button1_Click(object sender, EventArgs e)


{
this.Close();
}

Numele metodei button1_Clic este alctuit din numele controlului button1, urmat de
numele evenimentului: Clic.
150

Acum ar trebui s revenii la Form1 i executai dublu clic pe butonul din acest formular
pentru a ajunge la administratorul su de evenimente. Editai administratorul evenimentului
conform exemplului de mai jos:

private void button1_Click(object sender, EventArgs e) {


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

n acest moment rulai programul apsnd tasta F5 i vei 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
Deschidei o nou aplicaie Windows Forms, tragei dou controale de tip Button pe
formular pe care le redenumii cu DA i cu NU, un control de tip PictureBox i un control de tip
Label pe care scriei textul: Te crezi inteligent?.

Textul pentru fiecare control l vei introduce utiliznd proprietatea Text. Va trebui sa avei
dou imagini diferite salvate ntr-un folder pe calculatorul vostru.
Executai dublu clic pe butonul DA i folosii urmtorul 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 completai corect calea spre folder-ul n care ai salvat imaginea pentru importul
cu succes al ei.
Executai dublu clic pe butonul NU i folosii urmtorul cod pentru administratorul
evenimentului Clic:

private void button2_Click(object sender, EventArgs e) {


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

Vei obine la rularea aplicaiei afiarea uneia din cele dou imagini, n funcie de butonul apsat.

sau

Exemplul 4: Caset de text

Tot n cadrul evenimentului Clic, oferim acum un exemplu de afiare ntr-un TextBox a unui
mesaj, n momentul n care se execut clic pe un buton. Deschidei o nou aplicaie Windows
Forms. Tragei un control de tip Button pe formular i un control de tip TextBox. Modificai textul ce
apare pe buton, conform imaginii, i executai dublu clic pe el, pentru a ajunge la administratorul
su de evenimente. Modificai 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 rulai programul apsnd tasta F5 i facei clic pe buton.

152

Exemplul 5: Caset de mesaj


Pentru a crea o caset mesaj, apelm metoda MessageBox.Show();.ntr-o nou aplicaie
Windows Forms, tragei un control de tip Button n formular, modificai textul butonului cum dorii
sau ca n imaginea alturat va apare un mesaj, executai dublu clic pe buton i adugai n
administratorul evenimentului Clic linia de program: MessageBox.Show("ti-am spus");. Apoi
rulai aplicaia.

Exemplul 6:
Este un exemplu de utilizare a
Propietatea Checked

controalelor de selecie CheckBox i RadioButton.

indic dac am selectat controlul. Dac proprietatea ThreeState este

setat, atunci se schimb funcionalitatea acestor controale, n sensul c acestea vor permite
setarea unei alte stri. n acest caz, trebuie verificat propietatea CheckState(Checked,
Unchecked, Indeterminate) pentru a vedea starea controlului CheckBox.
Soluia unei probleme cu mai multe variante de rspuns este memorat cu ajutorul unor
checkbox-uri cu proprietatea ThreeState. Apsarea butonului Verific determin afiarea unei
etichete i a butoanelor radio DA i NU. Rspunsul este afiat ntr-un MessageBox.

153

Dup adugarea controalelor pe formular i setarea proprietilor 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: Construcia Fractalului


Se deschide o aplicaie Windows Forms pe care o vei denumi Fractal. Stabilii dimensiunea
formularului la 740 cu 540, stabilii culoarea de fond a formularului alegnd una dintre cele
predefinite din opiunea BackColor.
Cu ajutorul metodei Drag and drop plasai pe formular: dou controale de tip Label n care
vei introduce urmtoarele texte Construirea unui fractal (pentru eticheta poziionat n partea de
sus a formularului) i Introducei numrul de ptrate (pentru cea de a doua etichet pe care e
bine s o poziionai la o distan nu prea mare de prima), plasai pe formular i un control de tip
TextBox, un control de tip Button, i un control de tip Timer pentru care setai intervalul la 50.

154

Executnd dublu clic pe butonul Start va fi deschis codul surs. n funcia button1_Clic
iniializm variabila m cu valoarea 1 i pornim timer-ul.

private void button1_Click(object sender, EventArgs e)


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

n aceeai fereastr de cod scriem funcia 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 funcia
timer1_Tick cu apelul funciei 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 executai dublu clic pe Form1.Designer.cs pentru a declara


variabila global m, n zona de declaraii a funciei 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 aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.

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


Exemplul 8: Casete de dialog

156

Creai o nou aplicaie Windows Forms, apoi tragei un buton n formular i setai
proprietatea Text a butonului la : s avem un dialog, iar apoi executai dublu clic pe buton i
modificai numele metodei din button1_click n button1_MouseEnter apoi folosii urmtorul
cod pentru administratorul evenimentului MouseEnter.

private void button1_MouseEnter(object sender, EventArgs e)


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

Intrai n codul surs pentru Form1.Designer.cs i modificai 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 fr a


executa clic pe el, s se execute codul surs al metodei.
Creai un alt formular la acest proiect (alegei Add Windows Forms din meniul Project), apoi
n ordine: setai proprietatea ControlBox la valoarea false, setai proprietatea Text la caset de
dialog, tragei n formular un control de tip Label i setai proprietatea Text la scrie text, adugai
un control TextBox n formular, adugai dou controale de tip Button, setai proprietatea Text a
butonului din stnga la OK iar al celui din dreapta la Cancel, setai proprietatea DialogResult a
butonului din stanga la OK iar al celui din dreapta la Cancel, executai clic pe formularul casetei de
dialog i setai proprietatea AcceptButton la button1 iar proprietatea CancelButton la button2.
Acum executai dublu clic pe butonul OK i folosii urmtorul cod pentru administratorul
evenimentului Clic:

private void button1_Click(object sender, EventArgs e)


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

Executai dublu clic pe butonul Cancel i folosii urmtorul 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 adugai declaraia: public string textBoxText; iar la


sfritul clasei Form2 adugai proprietatea:
public string TextBoxText
{get{ return(textBoxText);}

Acum putei 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 aplicaie Windows Forms pe care o vei denumi Schimb culoarea. Din fereastra
Properties redenumii formularul. Stabilii dimensiunea formularului i culoarea de fond alegnd
una dintre cele predefinite din opiunea BackColor.
Cu ajutorul metodei Drag and drop plasai pe formular: un control de tip Button pe care vei
introduce textul START, un control de tip Button pe care vei introduce textul STOP, un control de
tip Label pe care vei introduce textul Schimb culoarea, un control de tip Timer.

158

Executai dublu clic pe butonul START i editai administratorul evenimentului conform


exemplului de mai jos:

private void button1_MouseLeave(object sender, EventArgs e)


{timer1.Start();}

Intrai n codul surs pentru Form1.Designer.cs i modificai 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 vei plimba mouse-ul pe deasupra imaginii butonului i nu la executarea clic-ului.
Executai dublu clic pe butonul STOP i inserai linia de cod timer1.Stop();
Declarai urmtoarea variabil ca fiind variabil local pentru clasa Form1
Random r = new Random(200);

Executai dublu clic pe controlul Timer i inserai 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 aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.

159

Exemplul 10: Trei culori


Acest exemplu afieaz un grup alctuit din 3 butoane, etichetate A,B respectiv C avnd
iniial culoarea roie. Apsarea unui buton determin schimbarea culorii acestuia n galben. La o
nou apsare butonul revine la culoare iniial. Acionarea butonului Starea butoanelor determin
afiarea ntr-o caset text a etichetelor butoanelor galbene. Caseta text devine vizibil atunci cnd
apsm prima oar acest buton. Culoarea butonului mare (verde/portocaliu) se schimb atunci
cnd mouse-ul este poziionat pe buton. Dup adugarea 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

Exemplul 11: Hyperlink


LinkLabel afieaz un text cu posibilitatea ca anumite pri ale textului (LinkArea) s fie
desenate ca i hyperlink-uri. Pentru a face link-ul funcional trebuie tratat evenimentul LinkCliced.
n acest exemplu, prima etichet permite afiarea coninutului discului C:, a doua legtur
este un link ctre 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 aplicaie Windows Forms pe care o vei denumi Culori. Din fereastra
Properties modificai numele formularului redenumindu-l. Stabilii dimensiunea formularului i
culoarea de fond alegnd una dintre cele predefinite din opiunea BackColor. Cu ajutorul metodei
Drag and drop plasai pe formular: un control de tip Button pe care vei introduce textul START, un
control de tip Timer iar din caseta Properties intervalul l setai la 50.
Executai dublu clic pe suprafaa formularului i completai clasa Form1 cu declararea
variabilelor locale conform modelului de mai jos:

Random r = new Random();


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

Executai dublu clic pe controlul timer i completai funcia 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++;
}

Executai dublu clic pe butonul START i completai funcia button1_Click conform


modelului de mai jos:
private void button1_Click(object sender, EventArgs e)
{graf = this.CreateGraphics();
timer1.Start();
}

n fereastra Solution Explorer executai dublu clic pe Form1.Designer.cs pentru a declara


variabilele globale i,cx,cy

n zona de declaraii a funciei InitializeComponent().

private System.Windows.Forms.Button button1;


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

n acest moment aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.

Metoda Dispose()

Exemplul 13:
163

Se adaug pe un formular dou butoane i o caset text. Apsarea primului buton va


determina afiarea textului din TextBox ntr-un MessageBox iar apsarea celui de-al doilea buton
va nchide aplicaia (metoda Dispose() va nchide aplicaia).
Dup adugarea celor dou butoane i a casetei text a fost schimbat textul afiat pe cele
dou butoane au fost scrise funciile 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
interfaa IEnumerable).
n acest exemplu elementele selectate din CheckedListBox se adaug n ListBox. Dup
adugarea pe formular a CheckedListBox-ului, stabilim colecia de itemi (Properties-ItemsCollection), butonul Selecie i ListBox-ul.
Evenimentul

Click

asociat

(listBox1.Items.Clear();)

butonului

Selectie

golete

mai

nti

listBox-ul

i dup aceea adaug n ordine fiecare element selectat din

CheckedListBox. Suplimentar se afieaz o etichet cu itemii selectai.

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
afia o colecie de elemente n unul din cele 4 moduri (Text, Text+Imagini mici, Imagini mari,
Detalii). Acesta este similar grafic cu ferestrele n care se afieaz fiierele dintr-un anumit director
din Windows Explorer. Fiind un control complex, conine foarte multe proprieti, printre care:

View ( selecteaz modul de afiare (LargeIcon, SmallIcon, Details, List)),

LargeImageList, SmallImageList (icon-urile de afiat n modurile LargeIcon, SmallIcon),

Columns (utilizat doar n modul Details, pentru a defini coloanele de afiat), Items (elementele
de afiat).
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",
Nota = 9 });
elevi.Add(new Elev() { Nume = "Nume 2",
Nota = 10 });
elevi.Add(new Elev() { Nume = "Nume 3",
Nota = 8 });
elevi.Add(new Elev() { Nume = "Nume 4",
Nota = 9 });
return elevi;
}
}
165

Prenume = "Prenume 1",


Prenume = "Prenume 2",
Prenume = "Prenume 3",
Prenume = "Prenume 4",

Proiectul nostru con ine


Form1.cs este acesta:

i un Form unde am aezat un control de tip ListView. Codul din

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 pregte te lista pentru datele care i vor fi servite: mai nti i adaug 3
coloane, iar apoi seteaz propriet i care in de modul de afo are al acesteia. La Form1_Load
(adic atunci cnd form-ul se ncarc) se vor lega datele (lista de elevi) de controlul de interfa .

166

Metoda Draw()
Exemplul 16: Aplicaia este un exemplu de utilizare a controlului ImageList. Acesta este un control
care conine 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 conine.
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 rulrii aplicaiei vei obine:

167

Evenimentul DateSelected
Exemplul 17: MonthCalendar
MonthCalendar afieaz un calendar prin care se poate selecta o dat (zi, luna, an) n mod
grafic. Proprietile mai importante sunt: MinDate, MaxDate, TodayDate ce reprezint data
minim/maxim selectabil i data curent (care apare afiat difereniat sau nu n funcie de
valorile proprietilor ShowToday,ShowTodayCircle.
Exist 2 evenimente pe care controlul le expune: DateSelected i DateChanged. n rutinele
de

tratare

acestor

evenimente,

programatorul

are

acces

la

un

obiect

de

tipul

DateRangeEventArgs care conine proprietile Start i End (reprezentnd intervalul de timp


selectat).
Formularul din aplicaie conine un calendar pentru care putem selecta un interval de
maximum 30 de zile, sunt afiate sptmnile i ziua curent. Intervalul selectat se afieaz prin
intermediul unei etichete. Dac se selecteaz o dat atunci aceasta va fi adugat ca item ntr-un
ComboBox (orice dat poate aprea cel mult o dat n list).
Dup adugarea celor 3 controale pe formular, stabilim proprietile pentru monthCalendar1
(ShowWeekNumber-True, MaxSelectionCount-30, etc.) i precizm ce se execut atunci cnd
selectm 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) afieaz 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 att textul afiat 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 apsat).

Exemplul 18: Modificare proprieti


n aplicaia urmtoare cele 3 butoane

ale toolbar-ului permit modificarea proprietilor

textului introdus n caset. Toolbar-ul se poate muta fr a depi spaiul 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 cnd apsm butonul de
mouse i/sau ne deplasm pe suprafaa 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: Fiiere

170

Exemplul permite, prin intermediul unui meniu, scrierea unui fiier Notpad, afiarea
continutului acestuia ntr-o caset text, schimbarea fontului i culorii de afiare, tergerea coninutului
casetei, afiarea unor informaii teoretice precum i Help dinamic. Au fost definite chei de acces
rapid pentru accesarea componentelor meniului.
File New permite scrierea unui fiier notepad nou
System.Diagnostics.Process.Start( "notepad" );

File Open selecteaz i afieaz n caseta text coninutul unui fiier 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 coninutul casetei text, File Exit nchide aplicaia
Window Font i Window Color permit stabilirea fontului/culorii textului afiat.
Help DinamicHelp acceseaz
System.Diagnostics.Process.Start("IExplore",
"http://msdn2.microsoft.com/en-us/default.aspx");

Help About PV afieaz n caseta text informaii despre implementarea unui meniu.

171

II.5.4.

Obiecte grafice

Spaiul System.Drawing conine tipuri care permit realizarea unor desene 2D i au rol
deosebit n proiectarea interfeelor grafice.
Un obiect de tip Point este reprezentat prin coordonatele unui punct ntr-un spaiul
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 spaiu. De exemplu, pentru a modifica poziia unui buton n fereastr putem
asigna un obiect de tip Point proprietii Location indicnd astfel poziia colului din stnga-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 conine date, tipuri i metode utile n lucrul cu culori. Fiind un tip valoare
(struct) i nu o clas, aceasta conine date i metode, ns nu permite instaniere, constructori,
destructor, motenire.
Color myColor = Color.Brown; button1.BackColor = myColor;

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


componente ale oricrei culori (red, green, blue).
Clasa Graphics este o clas sigilat reprezentnd o arie rectangular
reprezentri grafice. De exemplu, o linie frnt se poate realiza astfel:

172

care permite

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


Aplicaia este un exerciiu 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 urmtor se construiete 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 informaiilor de la utilizator

nainte ca informaiile de la utilizator s fie preluate i transmise ctre alte clase, este
necesar s fie validate.
Acest aspect este important, pentru a preveni posibilele erori. Astfel, dac utilizatorul
introduce o valoare real (float) cnd aplicaia ateapt un ntreg (int), este posibil ca aceasta s
se comporte neprevzut abia cteva secunde mai trziu, i dup multe apeluri de metode, fiind
foarte greu de identificat cauza primar a problemei.

II.5.5.(1) Validarea la nivel de cmp


Datele pot fi validate pe msur 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 situaii (de exemplu atunci cnd valorile introduse trebuie s se afle ntr-o anumit
relaie ntre ele), validarea se face la sfritul 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 realizm o aplicaie simpl, n care vom folosi


cteva controale i vom explica ceea ce se ntmpl din punct de vedere al programrii orientate
obiect.
Ne propunem s construim o fereastr cu un buton, pe care, dac-l apsm, s
deschid o alt fereastr cu un mesaj: BUNA ZIUA!
Pe fereastra care apare la iniializarea proiectului nostru, vom plasa un buton pe care
scriem: APASATI. Dm dublu clic pe respectivul buton i scriem codul n funcia generat de
aceast aciune:
MessageBox.Show("BUNA ZIUA!");

Pentru a compila i executa apsm F5. Obinem:

175

S analizm puin codul nostru, aducndu-ne aminte de noiunile de programare orientat


obiect studiate:

MessageBox este o clas din spaiul 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 cednd controlul.
Metoda Show are mai multe forme n clasa MessageBox, fiind supradefinit. Apelul
acestei funcii se va face n funcie de parametri.
S considerm acum apelul funciei 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 considerm n continuare apelul funciei 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 ncercm o alt form supradefinit a metodei Show, folosind patru


parametri: al patrulea se va referi la icoana care s apar, alturi de textul BUNA ZIUA. Avem la
dispoziie 9 icoane.
MessageBox.Show("BUNA ZIUA!", "Salut", MessageBoxButtons.YesNo,
MessageBoxIcon.Asterisk);

177

II.5.7.

Interfa definit de ctre utilizator

Sunt multe aplicaii n care, poate, dorim s ne realizm 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 rnd trebuie s ne desenm propria fereastr de viitoare aplicaii. Pentru aceasta
vom folosi, de exemplu, aplicaia Paint.
Desenm o figur geometric care va constitui viitoarea noastr fereastr. Presupunem c
dorim ca fereastra s aib forma de oval.

178

Colorm ovalul cu o culoare dorit, iar pentru fundal alegem orice culoare, reinnd codul ei
RGB

179

n cazul nostru: Red: 255 Greeen: 255 Blue: 0


Salvm 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 nct imaginea s fie toat n PictureBox
Deformez PictureBox-ul astfel nct ovalul desenat s ocupe o suprafa care s
corespund esteticii programatorului

180

Selectez Form1, iar la proprietile corespunztoare voi selecta:

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


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

Dac vom compila observm c obinem, 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 cnd inem cursorul mouse-ului apsat pe ea.

181

nchidem fereastra rezultat i ne continum proiectul.


Aducem n Fereastra noastr un buton pe care-l vom folosi pentru nchiderea ferestrei
rezultat

182

Scriem codul corespunztor dnd dublu clic pe buton:


this.Close();
Includem biblioteca User32.dll n codul nostru: User32.dll este o bibliotec ce conine rutine
pentru interfaa 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);

Dm clic pe PictureBox, ne ducem la Fereastra Properties i selectm evenimentele


legate de acest control. Dm dublu clic pe evenimentul MouseDown i scriem n Fereastra
Form1.cs codul corespunztor butonului stnga al mouse-ului, cod ce se refer la posibilitatea de
a putea prinde i deplasa interfaa 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
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
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], selectm Form1, iar la Properties alegem:


FormBorderStyle None

184

Apsm F5 i surpriz (plcut ): obinem ceea ce ne-am propus:

185

II.5.8.

Browser creat de ctre utilizator

O aplicaie 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, cuvnt care va apare pe
bara de titlu. n aceast fereastr aducem:

TextBox la care, la TextBox Tasks bifm MultiLine

Button la care-i schimbm Text-ul n GO

WebBrowser pe care l aliniem dup laturile din stnga, dreapta i jos a ferestrei.

Dm dublu clic pe butonul GO i scriem codul necesar navigrii:


webBrowser1.Navigate(textBox1.Text);

Rulm programul i n TextBox vom scrie o adres web. Surpriz plcut, navigatorul nostru
funcioneaz!

186

Necazurile ncep n momentul n care ncercm s maximizm fereastra browser-ului pentru


a putea vizualiza mai bine informaiile afiate. Din pcate n acel moment obinem:

187

Observm c fereastra WebBrowser-ului nu s-a maximizat odat cu cea a ferestrei aplicaiei.


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 opiunea Split Container
Task aleg Horizontal splitter orientation

188

Deformez cele dou panouri ale containerului astfel ncnt 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
Dm dublu clic pe butonul GO i scriem acelai cod ca mai nainte.
Rulm programul i observm c dac maximizm fereastra WebBrowser-ul rmne lipit
de marginile ferestrei.
Singurul lucru care nu ne mulumete este faptul c la maximizarea ferestrei TextBox-ul i
Button-ul rmn pe loc i nu ader la marginile ferestrei. S corectm acest lucru.
Selectm TextBox-ul. dup care din fereastra Properties dm clic n csua
corespunztoare proprietii Anchor. Suntem asistai grafic pentru a stabili partea n care dorim
ca TextBox-ul s fie lipit de margini.

189

Alegem Stnga, Dreapta i Sus dnd clic pe segmentele corespunztoare.


La fel procedm 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 mbuntit, n sensul adugrii de noi butoane care s ofere
utilizatorului opiuni 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 aceeai dimensiune folosind opiunile de pe
bara de instrumente:

Selectarea tuturor butoanelor se poate face fie cu clic i Ctrl pe fiecare, fie nconjurnd cu
mouse-ul respectivele butoane (n acest timp butonul stng al mouse-ului este apsat).
Pe butoane fiecare poate s pun, dup gustul su, imagini n loc de aceste simboluri.
190

Vom scrie n continuare codul corespunztor fiecrui buton, dnd 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 proporional a WebBrowser-ului, mpreun cu ferestra


aplicaiei, 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
executrii (Timer) sau de dialog (OpenFileDialog, SaveFileDialog, ColorDialog, FontDialog,
ContextMenu).
Dintre acestea vom studia n cele ce urmeaz controlul Timer asupra cruia are drept de
interaciune doar cel care dezvolt aplicaia.
Observm c aducnd din Toolbox controlul Timer, acesta nu se afieaz pe formular, el
aprnd ntr-o zon gri a suprafeei de lucru (Designer).

191

Vom stabili urmtoarele proprieti legate de Timer:


Proprietate
(Name)

Valoare
aplCeas

Explicaie

Enabled
Interval

True
1.000

Activarea controlului de timp


Numrul de milisecunde dintre apelurile la metoda
de tratare a evenimentului. Se stabileste, n cazul
de fa numrtoarea din secund n secund

Aducem n formular un control Label cu urmtoarele proprieti:


Control
label1

Proprietate
(Name)
AutoSize
BorderStyle
FontSize
Location

Valoare
labelCeas
False
Fixed3D
16,25, Bold
82;112
192

Text
Size
TextAlign

129;42
MiddleCenter

Dm clic pe icoana de la timer care are


numele aplCeas, iar la Events, la Tick selectm
aplCeas_Tick

Dm dublu clic pe aplCeas_Tick i inserm


codul:
private void lblCeas_Tick(object sender, EventArgs e)
{
DateTime OraCurenta = DateTime.Now;
lblCeas.Text=OraCurenta.ToLongTimeString();
}

Compilm

obinem

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 crem baza de date. Pentru a
realiza acest lucru trebuie s deschidei aplicaia Microsoft SQL Server Management Studio
Express, i s acceptai conectarea la server-ul local.

n momentul deschiderii aplicaiei fereastra acestei aplicaii va conine fereastra Object Explorer,
fereastra Sumarry i fereastra Properties.

Pentru a crea o nou baz de date din fereastra Object Explorer ce se afl n stnga
ferestrei principale, executai clic pe butonul din dreapta al mouse-ului dup selectarea folderului
Databases, de unde alegei opiunea New Database..

194

Denumii aceast baz de date (n exemplul de mai jos noi i-am spus CLASA). Creai un
tabel alegnd n acelai mod ca i cel prezentat mai sus opiunea New Table, din folder-ul Table.

Definii 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
utilizai unul dintre tipurile de date ce v apar n lista derulant

Stabilii cheia primar a tabelei prin selectarea rndului unde dorii s stabilii cheia primar
i apoi prin executarea unui clic pe butonul din dreapta al mouse-ului i alegerea opiunii Set
Primary Key.

195

Pentru a salva tabela creat pn acum executai clic dreapta pe numele tabelei, alegei
opiunea Save Table i stabilii 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 executai clic dreapta pe butonul
mouse-ului dup selectarea fiierului i alegei opiunea Open Table.

196

Deconectarea de la baza de date se realizeaz prin alegerea opiunii Disconect Object


Explorer din meniul File al aplicaie, iar n cazul n care aplicaia este deschis i dorim
reconectarea la baza de date alegem din meniul File opiunea Connect Object Explorer.

II.6.3.

Introducere n limbajul SQL

II.6.3.(1) Introducere ANSI SQL


Anumite instruciuni cum ar fi Alter sau Create nu sunt accesibile din meniu. Va trebui s
apelai la scrierea lor n cod. Acest lucru poate fi realizat cu ajutorul procedurilor stocate sau cu
ajutorul opiunii SQLCMD.
O procedur stocat este o secven de instruciuni SQL, salvat in baza de date, care
poate fi apelata de aplicaii diferite. Sql Server compileaz procedurile stocate, ceea ce creste
eficiena utilizrii lor. De asemenea, procedurile stocate pot avea parametri.
Dac operaiile efectuate pe server sunt mai multe (calcule complexe de ex.) atunci e mai
simplu s apelai la procesarea n Stored Procedures i s returnai doar o list mic de rezultate,
gata procesate. Asta mai ales cnd procesarea necesit prelucrarea unui volum mare de date.
Pentru a realiza acest lucru va trebui s alegei opiunea New Stored Procedure executnd
clic pe butonul din dreapta al mouse-ului pe folderul Stored Procedures din folderul
Programmability al bazei de date pe care o prelucrai.

197

II.6.3.(2) Select
Forma instruciunii SELECT conine 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 *. Cuvntul cheie DISTINCT
adugat dup cuvntul cheie SELECT elimin rndurile duplicat din rezultatele nregistrrii.
FROM specific lista tabelelor sau vizualizrilor de unde selectm 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
Instruciunea Insert este folosit pentru inserarea noilor rnduri de date n tabele. Ea poate fi
folosit n dou variante:
pentru a crea un singur rnd la fiecare rulare, n acest caz valorile pentru rndul de date
respectiv sunt specificate chiar n instruciune
INSERT INTO nume_tabel
[(lista_de_coloane)]
VALUES (lista_de_valori);
Observaie:
- lista de coloane este opional, dar dac este inclus trebuie s fie ncadrat ntre paranteze
- cuvntul cheie NULL poate fi folosit n lista de valori pentru specificarea unei valori nule
pentru o coloan
Exemplul2:

de utilizare a instruciunii INSERT cu includerea listei de coloane. Pentru a

vizualiza modificarea folosii instruciunea SELECT.


INSERT INTO [elev].[dbo].[T1]
([ID]
,[NUME])
VALUES
(<ID, numeric,>
,<NUME, nvarchar(50),>)

pentru a insera rnduri multiple ntr-un tabel se folosete o instruciune SELECT intern

Exemplul 3: n acest exemplu instruciunea SELECT va gsi valoarea maxim de pe coloana


ID,

va incrementa aceast

valoare cu o unitate, obinnd astfel cheia primar a unei noi

nregistrri, nregistrare care va primi pe coloana NUME valoarea POPESCU. Pentru a vizualiza
modificarea folosii instruciunea SELECT.
199

INSERT INTO elev.dbo.CLASA


(ID
,NUME)
SELECT MAX(ID)+1,'POPESCU'
FROM elev.dbo.CLASA

Observaie:
- lista de coloane este opional, dar dac este inclus trebuie s fie ncadrat ntre paranteze
- cuvntul cheie NULL poate fi folosit n instruciunea SELECT pentru specificarea unei valori
nule pentru o coloan

II.6.3.(4) Update
Instruciunea Update este folosit pentru actualizarea datelor din coloanele unui tabel
Sintaxa ei este urmtoarea:
UPDATE [elev].[dbo].[CLASA]
SET [ID] = <ID, numeric,>
,[NUME] = <NUME, nvarchar(50),>
WHERE <Search Conditions,,>

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


introducem 21. Cu ajutorul instruciunii Update vom modifica acest ID. Pentru a vizualiza
modificarea folosii instruciunea SELECT.

200

Observaii:
- clauza SET conine o list cu una sau mai multe coloane, mpreun cu o expresie care
specific noua valoare pentru fiecare coloan
- clauza WHERE conine o expresie care limiteaz rndurile ce vor fi actualizate. Dac o
omitem se vor actualiza toate rndurile tabelului.

II.6.3.(5) DELETE
Instruciunea DELETE terge unul sau mai multe rnduri dintr-un tabel. n instruciunea
DELETE nu sunt referite niciodat coloane, deoarece instruciunea terge rnduri ntregi de date,
inclusiv toate valorile datelor din rndurile afectate.
DELETE FROM [elev].[dbo].[CLASA]
WHERE <Search Conditions,,>

Exemplul 5: modificai numele elevului cu ID-ul 2 din ADAM n POPESCU, pentru a avea
dou nregistrri cu acelai nume.
UPDATE elev.dbo.CLASA
SET
NUME = 'POPESCU'
WHERE ID=2

Folosii acum instruciunea DELETE astfel:


DELETE FROM elev.dbo.CLASA
WHERE NUME='POPESCU'

Observaii:
- clauza WHERE este opional, dar ATENIE dac vei renuna la ea se vor terge toate
nregistrrile existente
- atunci cnd includei clauza WHERE ea specific rndurile care urmeaz a fi terse. Va fi
tears orice nregistrare pentru care condiia indicat este adevrat.

II.6.3.(6) Comenzi de manipulare tabele


MODIFY ne permite modificarea numelui unei coloane, modificarea tipului de date al unui
rnd, sau modificarea cheii primare.
201

ALTER
Dup ce ai creat un tabel, aproape tot ceea ce ai specificat n instruciunea CREATE
TABLE poate fi modificat folosind instruciunea ALTER TABLE. Cu ajutorul ei se pot specifica toate
restriciile necesare(cheie primar, cheie extern, unicitate, verificare, etc).
ALTER TABLE <nume tabela> ADD|DROP|MODIFY (specificaii privind coloana modificata sau nou creata);

Exemplul 6: dorim s adugm 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 cmp se stabilete numele i tipul acestuia, putnd nominaliza o serie de
parametri facultativi (sunt acceptate sau nu valorile nule, setarea valorii implicite, cmpul 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 folosii comanda Select ca in exemplul de mai
jos iar apoi executai clic pe mouse pe butonul

Dup cum observai se pot vizualiza cmpurile definite n tabela Flori. Pentru a popula
aceasta tabel trebuie s o deschidei cu Open.

II.6.3.(7) Manipularea datelor


FUNCIA COUNT returneaz numrul de cmpuri dintr-o tabel care corespund interogrii.
Sintaxa instruciunii este:
SELECT COUNT (nume coloana)
FROM nume tabel
WHERE <Search Conditions,,>

Exemplul 8: pentru tabela Salarii am cerut cte persoane au salariu mai mare dect 1200.

203

Funcia SUM returneaz suma total dintr-o coloan a crei tip de date a fost declarat
iniial numeric.
SELECT SUM(column_name) FROM table_name
Exemplul 9: pentru tabela Salarii cerem suma tuturor salariilor nregistrate pe coloana
Salar.

Funcia Max returneaz cea mai mare valoare nregistrat pe o coloan


Sintaxa: SELECT MAX(column_name) FROM table_name
Exemplul 10: cerem s se afieze cel mai mare salariu din tabela Salarii.

Funcia Min returneaz cea mai mic valoare nregistrat pe o coloan


Sintaxa: SELECT MIN(column_name) FROM table_name
Exemplul 11: cerem s se afieze cel mai mare salariu din tabela Salarii.

204

Ordonarea datelor dintr-o tabel se poate realiza cu ajutorul instruciunii 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 aplicaii. Conceptual, n spatele unei ferestre n care lucrm 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 informaiile nregistrate n tabela sau tabelele bazei
de date pot fi utilizate ntr-o aplicaie din Visual C# ntr-un formular sau ntr-o aplicaie 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 aplicaiei din fereastra Toolbox
tragei pe formular cu ajutorul procedeului drag-and-drop o DataGridView, conform exemplului de
mai jos.

205

Alegei sursa de date pentru acest proiect executnd clic pe butonul AddProject Data
Source din fereastra DataGridView Task, alegei imediat dup aceasta sursa de date i baza de
date urmrind exemplele de mai jos.

nainte de a finaliza prin executarea unui clic pe butonul Ok din fereastra Add Connection,
nu uitai s verificai conexiunea executnd clic pe butonul Test Connection.

Conexiunea la baza de date se finalizeaz prin alegerea obiectului pe care dorii s l utilizai
n formularul creat.

206

Dup finalizarea conexiunii sursa generat o putei 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
);
}}}

Rulai aplicaia alegnd opiunea Start Debugging din meniul Debug i vei obine afiarea
datelor ntr-un formular ca n exemplul de mai jos.

Afiarea nregistrrilor din tabel se poate obine i prin alegerea opiunii Preview din
fereastra DataGridView Task i executnd clic pe butonul Preview din fereastra care se deschide
Preview Data .

Cheia primar se poate stabili din fereastra SalariiDataset executnd clic pe butonul
din dreapta al mouse-ului i alegnd opiunea Set Primary Key pentru cmpul respectiv.

207

Stabilii cheia primar a tabelei prin selectarea rndului unde dorii s stabilii cheia primar
i apoi prin executarea unui clic pe butonul din dreapta al mouse-ului i alegerea opiunii Set
Primary Key.

Dup cum observai opiunile prezente n acest meniu v mai pot ajuta s tergei o coloan
n tabel, s inserai o coloan din tabel s stabilii sau s modificai proprietile unei coloane deja
definite sau s vizualizai codul generat.

II.7.2.

Operaii specifice prelucrrii tabelelor

Atunci cnd ntr-un formular utilizm un tabel trebuie s avem posibilitatea de a utiliza
funciile ce opereaz asupra datelor incluse n el. Toate instruciunile 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 instaniere, construirea barei de navigare care
faciliteaz operaii de deplasare, editare, tergere i adugare n tabel.
Se observ c reprezentarea vizual a fiecrui obiect este nzestrat cu o sget n partea
de sus, n dreapta. Un clic pe aceast sgeat activeaz un meniu contextual cu lista principalelor
operaii 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, operaiile permise i altele).
208

Prezentm un exemplu pentru inserarea unor noi date n tabelul Salar_Angajat:


alegai opiunea Add Query din SALAR_ANGATTableAdapter Tasks

introducei instruciunea INSERT n forma dorit, executai clic pe butonul Query Builder pentru
a vizualiza efectul, si clic pe butonul Execute Query pentru a o lansa n execuie

confirmarea introducerii noii nregistrri o vei obine imediat

pentru a vizualiza efectul acestei instruciuni putei lansa n execuie aplicaia


n acelai mod se pot utiliza celelalte instruciuni i funcii 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 fiier
text, o foaie Excel, un fiier Access sau un fiier XML.
In aplicaiile tradiionale cu baze de date, clienii stabilesc o conexiune cu baza de date i
menin aceast conexiune deschis pn la ncheierea executrii aplicaiei.
Conexiunile deschise necesit alocarea de resurse sistem. Atunci cnd meninem mai
multe conexiuni deschise server-ul de baze de date va rspunde mai lent la comenzile clienilor
ntruct cele mai multe baze de date permit un numr foarte mic de conexiuni concurente.
ADO.NET permite i lucrul n stil conectat dar i lucrul n stil deconectat, aplicaiile
conectndu-se la server-ul de baze de date numai pentru extragerea i actualizarea datelor. Acest
lucru permite reducerea numrului de conexiuni deschise simultan la sursele de date.
ADO.NET ofer instrumentele de utilizare i reprezentare XML pentru transferul datelor
ntre aplicaii i surse de date, furniznd o reprezentare comun a datelor, ceea ce permite
accesarea datelor din diferite surse de diferite tipuri i prelucrarea lor ca entiti, fr 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 interaciona uor cu orice component care suport XML.
Durabilitate. ADO.NET permite dezvoltarea arhitecturii unei aplicaii 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 cretere a productivitii i la o scdere a numrului de erori.
Performan. Nu mai este necesar conversia explicit a datelor la transferul ntre aplicaii, fapt
care duce la crete performanelor acestora.
Accesibilitate. Utilizarea arhitecturii deconectate permite accesul simultan la acelai set de
date. Reducerea numrului 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 existenei 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 interaciune 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 dect 7.0).
Furnizorul de date permite unei aplicaii 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 operaie cu o surs de date extern, trebuie realizat o conexiune (legtur)
cu acea surs. Clasele din categoria Connection (SQLConnection, OleDbConnection etc.) conin
date referitoare la sursa de date (locaia, numele i parola contului de acces, etc.), metode pentru
deschiderea/nchiderea conexiunii, pornirea unei tranzacii etc. Aceste clase se gsesc n subspaii
(SqlClient, OleDb etc.) ale spaiului System.Data. n plus, ele implementeaz interfaa
IdbConnection.
Pentru deschiderea unei conexiuni prin program se poate instania un obiect de tip conexiune,
precizndu-i ca parametru un ir de caractere coninnd date despre conexiune.
Toate exemplele pe care le vom prezenta n continuare vor avea la baz o tabel cu
urmtoarea structur:

Exemplul 2: conexiunea se face introducnd explicit numele serverului ca n exemplul de mai


jos
SqlConnection con = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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 ) definete un ir care permite


identificarea tipului i sursei de date la care se face conectarea i eventual contul i parola de
acces. Conine lista de parametri necesari conectrii sub forma parametru=valoare, separai prin ;.
Parametru

Descriere
Specific furnizorul de date pentru conectarea la sursa de date. Acest furnizor
Provider trebuie precizat doar dac se folosete 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 gseasc 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 corespunztoare ID-ului specificat.
ConnectionTimeout (int, cu accesor de tip get): specific numrul de secunde pentru care un
obiect de conexiune poate s atepte pentru realizarea conectrii la server nainte de a se genera
o excepie. (implicit 15). Se poate specifica o valoare diferit de 15 n ConnectionString folosind
parametrul Connect Timeout, Valoarea Timeout=0 specific ateptare 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 sa fcut conectarea.
Este necesar pentru a arta 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 sa fcut 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 tranzacii pe baza de date; la sfrit 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 acelai 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 cnd se schimb starea conexiunii. Handlerul corespunztor (de tipul
delegat StateChangeEventHandler) spune ntre ce stri s-a fcut tranziia.
InfoMessage: apare cnd furnizorul trimite un avertisment sau un mesaj ctre client.

II.8.4.

Comenzi

Clasele din categoria Command (SQLCommand, OleDbCommand etc.) conin date


referitoare la o comand SQL (SELECT, INSERT, DELETE, UPDATE) i metode pentru
executarea unei comenzi sau a unor proceduri stocate. Aceste clase implementeaz interfaa
IDbCommand. Ca urmare a interogrii unei baze de date se obin obiecte din categoriile
DataReader sau DataSet. O comand se poate executa numai dup ce s-a stabilit o conxiune cu
baza de date corespunztoare.
Obiectele de tip SQLCommand pot fi utilizate ntr-un scenariu ce presupune deconectarea
de la sursa de date dar i n operaii elementare care presupun obinerea unor rezultate imediate.
Vom exemplifica utilizarea obiectelor de tip Command n operaii ce corespund acestui caz.

II.8.4.(1) Proprieti
CommandText (String): conine comanda SQL sau numele procedurii stocate care se execut
pe sursa de date.
CommandTimeout (int): reprezint numrul de secunde care trebuie s fie ateptat pentru
executarea comenzii. Dac se depeste acest timp, atunci se genereaz o excepie.
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 obinuit), TableDirect (numai pentru OleDb)
Connection (System. Data. [Provider].PrefixConnection): conine obiectul de tip conexiune
folosit pentru legarea la sursa de date.
Parameters (System.Data.[Provider].PrefixParameterCollection): returneaz o colecie de
parametri care s-au transmis comenzii.
Transaction (System.Data.[Provider].PrefixTransaction): permite accesul la obiectul de tip
tranzacie 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 aplicaia
curent (sub forma unui obiect din categoria DataSet).
Clasele DataReader permit parcurgerea ntr-un singur sens a sursei de date, fr
posibilitate de modificare a datelor la surs. Dac se dorete modificarea datelor la surs, se va
utiliza ansamblul DataAdapter + DataSet. Datorit faptului c citete 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 aplicaie este nevoie doar de informaii care vor fi citite o singura dat, sau
rezultatul unei interogri este prea mare ca sa fie reinut n memorie (caching) DataReader este
soluia cea mai bun.
Un obiect DataReader nu are constructor, ci se obine cu ajutorul unui obiect de tip
Command i prin apelul metodei ExecuteReader() (vezi exerciiile 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

interfaa

IDataReader.

II.8.5.(1) Proprieti:
IsClosed (boolean, read-only)- returnez true dac obiectul este deschis i fals altfel
HasRows (boolean,read-only)- verific dac reader-ul conine cel puin o nregistrare
Item (indexator de cmpuri)
FieldCount-returneaz numrul de cmpuri 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 cmp
specificat, din nregistrarea curent
GetBytes(), GetChars() citirea unor octei/caractere dintr-un cmp de date binar
GetDataTypeName(), GetName() returneaz tipul/numele cmpului specificat
IsDBNull() returneaz true dac n cmpul specificat prin index este o valoare NULL
NextResult()determin trecerea la urmtorul rezultat stocat n obiect (vezi exemplul)
Read() determin trecerea la urmtoarea nregistrare, returnnd false numai dac aceasta nu
exist; de reinut c iniial poziia curent este naintea primei nregistrri.
DataReader obine datele ntr-un stream secvenial. Pentru a citi aceste informaii trebuie

apelat metoda Read; aceasta citete un singur rnd din tabelul rezultat. Metoda clasic de a citi
informaia 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() oprete 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 numrul de
nregistrri afectate.
Exemplul 4: se va terge nregistrarea cu numele PREDA i se va returna un obiect afectat
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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 obine coninutul tabelei ntr-un obiect de tip SqlDataReader.
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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. Coninutul
ei este prezentat mai jos.

De data aceasta vom afia coninutul ambelor tabele.


SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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

opional

de

tip

enumerare,

CommandBehavior, care descrie rezultatele i efectul asupra bazei de date:


- CloseConnection (conexiunea este nchis atunci cnd obiectul DataReader este nchis),
- KeyInfo (returnez informaie despre coloane i cheia primar),
- SchemaOnly (returnez doar informaie 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 citete codul
care sunt coloanele afiate dect 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 folosete 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 afieaz datele nregistrate
pe coloana NUME.
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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=DANAD90FDEF1A8\\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 rnd a


setului de date rezultat. Este folosit pentru obinerea unor rezultate statistice.
Exemplul 8:

217

Int32 var = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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 utilizm metoda
ExecuteReader care returneaz un obiect SqlDataReader.
// Instaniem o comand cu o cerere i precizm conexiunea
SqlCommand cmd = new SqlCommand("select salar from salar_angajat", co);
// Obinem rezultatul cererii
SqlDataReader rdr = cmd.ExecuteReader();

II.8.8.

Inserarea datelor

Pentru a insera date ntr-o baz de date utilizm metoda ExecuteNonQuery a obiectului
SqlCommand .
// irul care pstreaz comanda de inserare
string insertString = @"insert into salar_angajat(ID,NUME,PRENUME,VECHIME,SALAR)
values (6 ,'BARBU' ,'EUGENIU', 17,1993)";
// Instaniem o comand cu acest cerere i precizm conexiunea
SqlCommand cmd = new SqlCommand(insertString, co);
// Apelm metoda ExecuteNonQuery pentru a executa comanda
cmd.ExecuteNonQuery();

218

Exemplul 9: vom insera n tabela salar_angajat o nou nregistrare i vom afia tot coninutul
tabelei
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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
SALAR_ANGAJAT i vom afia tot coninutul tabelei

n tabela

SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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();//Apelm 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 aceeai metod ExecuteNonQuery.
Exemplul 11: vom terge nregistrarea cu numele BIBIRE din tabela SALAR_ANGAJAT i
vom afia tot coninutul tabelei
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
// irul care pstreaz comanda de tergere
string deleteString = @"delete from SALAR_ANGAJAT where NUME
= 'BIBIRE'";
// Instaniem o comand
SqlCommand cmd = new SqlCommand();
// Setm proprietatea CommandText
cmd.CommandText = deleteString;
// Setm proprietatea Connection
cmd.Connection = co;
// . Executm 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: Realizai o conexiune la baza de date SALAR_ANGAJAT i afiai cea mai
mare vechime i suma tuturor salariilor nregistrate.
Int32 var = 0; Int32 suma = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\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: Realizai funcii care s implementeze operaiile elementare asupra unei
baze de date i verificai funcionalitatea lor.
conexiunea la baza de date
class program
{
SqlConnection conn;
public program()
{
conn = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");}

apelarea din funcia main a funciilor care vor realiza afiarea 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();
}

funcia de citire i afiare 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(); }
}
}

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

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

funcia care terge una sau mai multe nregistrri n funcie de condiia 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(); } }
}

funcia care numr nregistrrile 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 operaii de selectare,
tergere, modificare i adugare la baza de date. Clasele DataAdapter genereaz obiecte care
funcioneaz ca o interfa ntre sursa de date i obiectele DataSet interne aplicaiei, permind
prelucrri pe baza de date. Ele gestioneaz automat conexiunea cu baza de date astfel nct
conexiunea s se fac numai atunci cnd este imperios necesar.
Un obiect DataSet este de fapt un set de tabele relaionate. Folosete serviciile unui obiect
DataAdapter pentru a-i procura datele i trimite modificrile napoi ctre baza de date. Datele sunt
stocate de un DataSet n format XML, acelai folosit i pentru transferul datelor.
n exemplul urmtor 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

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

Proprieti
DeleteCommand, InsertCommand, SelectCommand, UpdateCommand (Command), conin
comenzile ce se execut pentru selectarea sau modificarea datelor n sursa de date.
MissingSchemaAction (enumerare) determin ce se face atunci cnd datele aduse nu se
potrivesc peste schema tablei n care sunt depuse. Poate avea urmtoarele valori:
Add - implicit, DataAdapter adaug coloana la schema tablei
AddWithKey se adaug coloana i informaii relativ la cheia primar
Ignore - se ignor lipsa coloanei respective, ceea ce duce la pierdere de date
223

Error - se genereaz o excepie 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, numrul
de nregistrare cu care s se nceap popularea (prima avnd indicele 0) i numrul de nregistrri
care urmeaz a fi aduse.
Update() permite transmiterea modificrilor efectuate ntr-un DataSet ctre baza de date.
Un DataSet este format din Tables (colecie format din obiecte de tip
DataTable este compus la rndul lui

DataTable;

dintr-o colecie de DataRow i DataColumn), Relations

(colecie de obiecte de tip DataRelation pentru memorarea legturilor printecopil) i


ExtendedProperties ce conine proprieti definite de utilizator.
Scenariul uzual de lucru cu datele dintr-o tabel conine urmtoarele etape:
popularea succesiv a unui DataSet prin intermediul unuia sau mai multor obiecte DataAdapter,
apelnd 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 corespunztoare operaiilor INSERT, UPDATE i
DELETE. Un obiect CommandBuilder poate construi automat o combinaie de comenzi ce reflect
modificrile efectuate.
Aadar, DataAdapter deschide o conexiune doar atunci cnd este nevoie i o nchide

imediat aceasta nu mai este necesar.


De exemplu DataAdapter realizeaz urmtoarele operaiuni atunci cnd trebuie sa populeze
un DataSet:deschide conexiunea, populeaz DataSet-ul,nchide conexiunea i urmtoarele
operaiuni atunci cnd trebuie sa fac update pe baza de date: deschide conexiunea, scrie
modificrile din DataSet n baza de date, nchide conexiunea. ntre operaiunea de populare a
DataSet-ului i cea de update conexiunile sunt nchise. Intre aceste operaii 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 totui o suprancrcare a
acestuia care primete ca parametru un string i este folosit atunci cnd trebuie s se fac o
serializare a datelor ntr-un fiier XML. n exemplul anterior avem un DataSet gol i avem nevoie
de un DataAdapter pentru a-l popula.
Un obiect DataAdapter conine mai multe obiecte Command (pentru inserare, update,
delete i select) i un obiect Connection pentru a citi i scrie date.

224

n exemplul urmtor 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 instania doar comanda de interogare. Instanierea


celorlalte se face fie prin intermediul proprietilor pe care le expune DataAdapter, fie folosind
obiecte de tipul CommandBuilder.
SqlCommandBuilder cmdBldr = new SqlCommandBuilder (daSALAR);

La iniializarea unui CommandBuilder se apeleaz

un constructor care primete ca

parametru un adapter, pentru care vor fi construite comenzile. SqlCommandBuilder are nu poate
construi dect comenzi simple i care se aplica unui singur tabel. Atunci cnd trebui ca sa facem
comenzi care vor folosi mai multe tabele este recomandata construirea separat a comenzilor i
apoi ataarea lor adapterului folosind proprieti.
Popularea DataSet-ului se face dup ce am construit cele dou instane:
daSALAR.Fill (dsNUME, "NUME");

n exemplul urmtor 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 adugate 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 fcute modificri 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.

Aplicaie final
Pentru a realiza aceast aplicaie trebuie s creai o baz de date (noi am numit-o

salarii) baz n care trebuie s creai o tabel (noi am anumit-o salar_angajat) cu cinci cmpuri (ID,
NUME, PRENUME, VECHIME, SALAR) pe care o putei popula cu cteva nregistrri.
Noi ne-am propus s crem o aplicaie care s:
- insereze una sau mai multe nregistrri,
- s tearg una sau mai multe nregistrri,
- s afieze permanent numrul de astfel de modificri efectuate,
- s afieze coninutul tabelei dup fiecare modificare,
- s calculeze suma salariilor din tabel
- s afieze cel mai mare salar
- s afieze cea mai mic vechime
- s afieze nregistrrile n ordine lexicografic
Pentru a realiza i voi acelai lucru va trebui s parcurgei paii explicai n continuare.
Din meniul File al aplicaiei Microsoft Visual C# 2008 Express Edition alegei New
Project/Windows Forms Application. Pe formular va trebui s tragei un buton (INSERARE), cinci
etichete(ID, NUME, PRENUME, VECHIME, SALAR), cinci casete de text poziionate sub fiecare
etichet, o etichet n care s introducei textul NUMR DE MODIFICRI, iar n dreptul ei o
caset de text. Urmrii imaginea din figura de mai jos:

n sursa din spatele formularului declarai o variabil de tip int nrmodificari care va contoriza
permanent numrul de modificri aduse tabelei (tergeri, inserri) i conexiunea la baza de date.
public partial class Form1 : Form
{
int nrmodificari = 0; SqlConnection co;
public Form1()
{
InitializeComponent();
226

co
=
new
SqlConnection(@"Data
D90FDEF1A8\SQLEXPRESS;Database=dana;Trusted_Connection=yes;");
co.Open();
}

Source=DANA-

Executai ciclk dublu pe butonul INSERARE i completai sursa lui cu instruciunile care
vor permite inserarea unor nregistrri noi n tabel. Numrul de inserri l vei putea vizualiza n
caseta de text asociat etichetei cu numele NUMR DE MODIFICRI.
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 coninutul tabelei pe formular va trebui s mai tragei un buton


AFISARE , patru etichete (pentru nume,prenume,vechime i salar), iar n sursa butonului
AFISARE s completai codul de mai jos, cod care v va permite afiarea celor patru cmpuri
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 ntoarcei acum pe formular n mod design, i mai adugai un buton pe care noi lam numit STERGERE, o etichet n care va trebui s introducei textul INTRODUCETI NUMELE
ANGAJATULUI CE TREBUIE STERS i o caset de text, pe care o vei poziiona n dreptul
etichetei.

Executai clic dublu pe butonul STERGE i completai sursa cu codul care v va


permite tergerea unui angajat al crui 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 obine suma salariilor din tabel va trebui s completai formularul n mod
design cu nc un buton cel pe care noi l+am numit SUMA SALARII, n dreptul lui s adugai o

228

caset de text i s completai sursa butonului cu codul care v va permite obinerea sumei
salariilor nregistrate n tabel apelnd funcia 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 pregtii suprafaa formularului pentru includerea unor noi butoane,
casete de text i etichete, prin :
modificarea poziiilor celor deja existente
adugarea a patru etichete pe care vor fi introduse textele NUME, PRENUME, VECHIME,
SALAR

229

Adugai dou butoane i dou casete de text pe care ncercai s le poziionai 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 adugai un buton pe care vei insera textul: AFISARE IN
ORDINE LEXICOGRAFICA, i completai sursa lui cu urmtorul 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 putei spune c ai creat o aplicaie care v ajut s gestionai ntr-o
oarecare msur o tabel a unei baze de date. Toate funciile i comenzile SQL prezentate n
acest capitol se pot regsi ntr-o aplicaie de acest gen. Totul este s v stabilii prioritile nainte
de a v apuca de lucru, iar dac pe parcurs mai dorii s adugai sau s modificai aplicaia ai
observat c acest lucru este posibil.

231

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