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

2
I. Programare orientat pe obiecte

I.1. Introducere in .NET

.NET este un cadru (Framework) de dezvoltare software unitar care permite realizarea,
distribuirea i rularea 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

Data and XML classes


(ADO.NET, SQL, XML etc.)

FCL
Framework Base Classes
(IO, securitate, fire de execuie, colecii etc.)

CLR
Common Language Runtime
(execepii, validri de tipuri,compilatoare JIT)

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.

4
n plus, CLR se ocup de gestionarea automat a memoriei (un mecanism implementat n
platforma .NET fiind acela de eliberare automat a zonelor de memorie asociate unor date
devenite inutile Garbage Collection).
Ca un element de portabilitate, trebuie spus c .NET Framework este implementarea unui
standard numit Common Language Infrastructure
(http://www.ecma-international.org/publications/standards/Ecma-335.htm ),
ceea ce permite rularea 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

6
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 using System;
2
3 namespace HelloWorld
4 {
5 class Program
6 {
7 static void Main()
8 {
9 Console.WriteLine("Hello World!");
10 }
11 }
12 }

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

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

n C#, simplificat vorbind, un program poate namespace

fi privit ca avnd mai multe straturi: avem cod n class


interiorul metodelor, care, la rndul lor, se afl n
metod
interiorul claselor, aflate n interiorul
namespaces-urilor.
cod

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

9
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 as base bool break


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

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

ascending by descending equals from


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

n general, cuvintele cheie nu pot fi folosite n programele pe care le scriem, 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; //gresit, constanta nu a fost initializata


const int x = 13; //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; //corect


readonly int x = 13; //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 Tip Operatori Asociativitate


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

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

namespace Exemplul_6
{
class Program
{
static void Main(string[] args)
{
bool v1, v2;
v1 = true; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = true; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = false; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
v1 = false; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = " + "{0,6}",
v1, v2, v1 & v2);
Console.ReadKey();
}
}
}

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

namespace Exemplul_9
{
class Program
{
static void Main(string[] args)
{
byte a = 13; // byte intreg fara semn pe 8 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 n
sbyte short, int, long, float, double, decimal
byte short, ushort, int, uint, long, ulong, float, double, decimal
short int, long, float, double, decimal
ushort int, uint, long, ulong, float, double, decimal
int long, float, double, decimal
uint long, ulong, float, double, decimal
long float, double, decimal
char ushort, int, uint, long, ulong, float, double, decimal
float double
ulong float, double, decimal

I.2.4.8.2. Conversia explicit

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

din n
sbyte byte, ushort, uint, ulong, char
byte sbyte, char
short sbyte, byte, ushort, uint, ulong, char
ushort sbyte, byte, short, char
int sbyte, byte, short, ushort, uint, ulong, char
uint sbyte,byte, short, ushort, int, char
long sbyte, byte, short, ushort, int, uint, ulong, char
ulong sbyte, byte, short, ushort, int, uint, long, char
char sbyte, byte, short
float sbyte, byte, short, ushort, int, uint, long, ulong, char, decimal
double sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
decimal
decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double

18
Exemplul 10:

using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_10
{
class Program
{
static void Main(string[] args)
{
int a = 5;
int b = 2;
float c;
c = (float)a / b; //operatorul cast
Console.WriteLine("{0} / {1} = {2}", a, b, c);
Console.WriteLine("Catul intregilor, reprezentat ca real datorita
operatorului cast\nde conversie explicita");
}
}
}

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

namespace Exemplul_13
{
class Program
{
static void Main(string[] args)
{
short srez, sv = 13;
int iv = 123;
long lrez;
float frez, fv = 13.47F;
double drez, dv = 87.86;
string strrez, strv = "15";
bool bv = false;

Console.WriteLine("Exemple de conversii:\n");

Console.WriteLine("Implicite:");
drez = fv + sv;
Console.WriteLine("float si short spre double {0} + {1} = {2}",
fv, sv, drez);
frez = iv + sv;
Console.WriteLine("int si short spre float {0} + {1} = {2}\n",
iv, sv, frez);

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

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


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

lrez = iv + Convert.ToInt64(strv);
Console.WriteLine("int si string cu ToInt64 spre long {0} + {1} =
{2}", iv, strv, lrez);
}
}
}

20
I.2.4.8.3. Conversii boxing i unboxing

Datorit faptului c n C# toate tipurile sunt derivate din clasa Object (System.Object),
prin conversiile boxing (mpachetare) i unboxing (despachetare) este permis tratarea tipurilor
valoare drept obiecte i reciproc. Prin conversia boxing a unui tip valoare, care se 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 heap


iniializeaz o variabil de tip valoare, care va conine i
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
int
referitoare la tipul de dat coninut. object ob=i; 13

21
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; //boxing implicit
i = (int)ob; //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 int int.Parse(ir) sau Int32.Parse(ir)
ir long long.Parse(ir) sau Int64.Parse(ir)
ir double double.Parse(ir) sau Double.Parse(ir)
ir float float.Parse(ir) sau Float.Parse(ir)

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


acestui ir la numr va eua.

Exemplul 18:

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

namespace Exemplul_18
{
class Program
{
static void Main(string[] args)
{
string s;
const int a = 13;
const long b = 100000;
const float c = 2.15F;
double d = 3.1415;

Console.WriteLine("CONVERSII\n");
Console.WriteLine("TIP\tVAL. \tSTRING");
Console.WriteLine("----------------------");
s = "" + a;
Console.WriteLine("int\t{0} \t{1}", a, s);
s = "" + b;
Console.WriteLine("long\t{0} \t{1}", b, s);
s = "" + c;
Console.WriteLine("float\t{0} \t{1}", c, s);
s = "" + d;
Console.WriteLine("double\t{0} \t{1}", d, s);
Console.WriteLine("\nSTRING\tVAL \tTIP");
Console.WriteLine("----------------------");
int a1;
a1 = int.Parse("13");

23
Console.WriteLine("{0}\t{1}\tint", "13", a1);
long b2;
b2 = long.Parse("1000");
Console.WriteLine("{0}\t{1} \tlong", "1000", b2);
float c2;
c2 = float.Parse("2,15");
Console.WriteLine("{0}\t{1} \tfloat", "2,15", c2);
double d2;
d2 = double.Parse("3.1415",
System.Globalization.CultureInfo.InvariantCulture);

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


Console.ReadKey();
}
}
}

I.2.5. Tipuri de date

n C# exist dou categorii de tipuri de date:


tipuri valoare
- tipul simplu predefinit: byte, char, int, float etc.
- tipul enumerare enum
- tipul structur - struct
tipuri referin
- tipul clas class
- tipul interfa interface
- tipul delegat delegate
- tipul tablou - array
24
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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExempluTipuriReferinta
{
class Program
{
static void Main(string[] args)
{
StringBuilder a = new StringBuilder();
StringBuilder b = a;
a.Append("Salut");
Console.WriteLine("a este '{0}'.", a);
Console.WriteLine("b este '{0}' prin initializare.", b);
a = null;
Console.WriteLine("a este '{0}' prin atribuirea unei noi
valori.", a);
Console.WriteLine("b este '{0}'.", b);
Console.ReadLine();
}
}
}

I.2.5.1. Tipul valoare

I.2.5.1.1. Tipuri predefinite

Limbajul C# conine un set de tipuri predefinite (int, bool etc.) i permite definirea unor
tipuri proprii (enum, struct, class etc.).

26
Tipuri simple predefinite

Tip Descriere Alias pentru tipul struct


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

Domeniul de valori pentru tipurile numerice:

Tip Domeniul de valori


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

O valoare se asigneaz dup urmtoarele reguli:

Sufix Tip
nu are int, uint, long, ulong
u, U uint, ulong
L, L long, ulong
ul, lu, Ul, lU, UL, LU, Lu ulong

27
Exemplul 21:

string s = Salut! float g = 1.234F;


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

I.2.5.1.2. Tipul enumerare

Tipul enumerare, 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 o astfel de posibilitate, folosind structura System.Nullable<T>.
Concret, o declaraie de forma:
System.Nullable<T> var;
este echivalent cu
T? var;
unde T este un tip valoare.

29
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 y1 1
x2 y2 1 = 0
x3 y3 1
E=(x2-x1)(y3-y1)-(x3-x1)(y2-y1)=0

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

namespace Exemplul_24
{
class Program
{
static void Main(string[] args)
{
double x1, y1, x2, y2, x3, y3;
Console.WriteLine("Coordonatele primului punct:");
Console.Write("Abscisa : ");
x1 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y1 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al doilea punct:");
Console.Write("Abscisa : ");
x2 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y2 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al treilea punct:");
Console.Write("Abscisa : ");
x3 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y3 = Convert.ToDouble(System.Console.ReadLine());

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

if (E == 0) Console.WriteLine("Puncte coliniare");
else Console.WriteLine("Puncte necoliniare");
}
}
}

31
Exemplul 25: S se verifice dac un numr ntreg x este ntr-un interval dat [a, b]

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

namespace Exemplul_25
{
class Program
{
static void Main(string[] args)
{
int a, b, x;
Console.WriteLine("Se citesc doua numere care vor reprezenta
capetele intervalului");
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
if (a > b)
{
x = a;
a = b;
b = x;
} // interschimbarea valorilor pentru a avea intervalul [a, b]
Console.Write("x = ");
x = Convert.ToInt32(Console.ReadLine());
if (x >= a && x <= b)
Console.WriteLine("Numarul {0} este in intervalul [ {1}, {2}
]", x, a, b);
else
Console.WriteLine("Numarul {0} nu este in intervalul [ {1},
{2} ]", x, a, b);
}
}
}

32
I.2.6.2. 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_26
{
class Program
{
static void Main(string[] args)
{
int x, n, k, ux;
Console.Write("Dati un numar natural ca baza a puterii : ");
x = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati un numar natural ca exponent al puterii : ");
n = Convert.ToInt32(Console.ReadLine());

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


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

if (n == 0) Console.WriteLine(" 1 ");
else
switch (ux)
{
case 0: Console.WriteLine(" 0 "); break;
case 1: Console.WriteLine(" 1 "); break;
case 2:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 "); break;
case 1: Console.WriteLine(" 2 "); break;
case 2: Console.WriteLine(" 4 "); break;
case 3: Console.WriteLine(" 8 "); break;
}
break;

33
case 3:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 "); break;
case 1: Console.WriteLine(" 3 "); break;
case 2: Console.WriteLine(" 9 "); break;
case 3: Console.WriteLine(" 7 "); break;
}
break;
case 4:
if (n % 2 == 0) Console.WriteLine(" 6 ");
else Console.WriteLine(" 4 ");
break;
case 5:
Console.WriteLine(" 5 ");
break;
case 6:
Console.WriteLine(" 6 ");
break;
case 7:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 "); break;
case 1: Console.WriteLine(" 7 "); break;
case 2: Console.WriteLine(" 9 "); break;
case 3: Console.WriteLine(" 3 "); break;
}
break;
case 8:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 "); break;
case 1: Console.WriteLine(" 8 "); break;
case 2: Console.WriteLine(" 4 "); break;
case 3: Console.WriteLine(" 2 "); break;
}
break;
case 9:
if (n % 2 == 0) Console.WriteLine(" 1 ");
else Console.WriteLine(" 9 ");
break;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

34
Exemplul 27: Programul 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_30
{
class Program
{
static void Main(string[] args)
{
int a, b, r, x, y;
Console.Write("Dati primul numar : ");
a = Convert.ToInt32(Console.ReadLine());

37
Console.Write("Dati al doilea numar : ");
b = Convert.ToInt32(Console.ReadLine());

x = a;
y = b;
r = x % y;
while (r != 0)
{
x = y;
y = r;
r = x % y;
}
if (y != 1)
Console.WriteLine("Cmmdc ({0}, {1}) = {2} ", a, b, y);
else
Console.WriteLine("{0} si {1} sunt prime intre ele ", a, b);
Console.WriteLine("Cmmmc ({0}, {1}) = {2}", a, b, a / y * b);
Console.ReadKey();
}
}
}

Exemplul 31: Dintr-un 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_31
{
class Program
{
static void Main(string[] args)
{
uint n, min, v;
Console.Write("Dati un numar intreg pozitiv : ");
n = Convert.ToUInt32(Console.ReadLine());
min = MinCifra(n);
v = Valoare(n, min);
Console.WriteLine("Eliminand cifra minima {0} din {1} obtinem
{2}", min, n, v);
}

38
static uint MinCifra(uint x)
{
uint min = 9;
while (x != 0)
{
if (x % 10 < min) min = x % 10;
x /= 10;
}
return min;
}
static uint Valoare(uint x, uint min)
{
uint y = 0, p = 1;
while (x != 0)
{
if (x % 10 != min)
{
y = y + (x % 10) * p;
p *= 10;
}
x /= 10;
}
return y;
}
}
}

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

namespace Exemplul_33
{
class Program
{
static void Main(string[] args)
{
int x, n, k = 0;
do
{
Console.Write("Dati un numar natural : ");
n = Convert.ToInt32(Console.ReadLine());
if (n <= 0)
Console.WriteLine("Eroare la citire!");
} while (n <= 0);
Console.Write("Numerele palindroame mai mici strict decat {0}
sunt :\n", n);
x = 1;

40
do
{
if (palindrom(x) == 1)
{
Console.Write(" {0,3} ", x);
k++;
}
x++;
} while (x < n);
Console.WriteLine();
if (k == 0) Console.WriteLine("Nu exista numere!");
else Console.WriteLine("Sunt {0} numere palindroame!", k);
}
static uint palindrom(int x)
{
int y = 0, z = x;
do
{
y = y * 10 + z % 10;
z /= 10;
} while (z != 0);
if (y == x) return 1;
else return 0;
}
}
}

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

namespace Exemplul_35
{
class Program
{
static void Main(string[] args)
{
int a, b, x, k = 0; // k va determina cate numere prime sunt in
interval
do
{
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
} while (a <= 0);
do
{
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
} while (b <= a);

42
Console.Write("Numerele prime : ");
for (x = a; x <= b; x++)
if (prim(x) == 1)
{
Console.Write("{0, 3}", x);
k++;
}
Console.WriteLine();
if (k == 0)
Console.WriteLine("In intervalul [ {0}, {1} ] nu sunt numere
prime!", a, b);
else
Console.WriteLine("In intervalul [ {0}, {1} ] sunt {2} numere
prime!", a, b, k);
}
static int prim(int x)
{
if (x == 1) return 0;
if (x % 2 == 0 && x != 2) return 0;
for (int d = 3; d * d <= x; d += 2)
if (x % d == 0) return 0;
return 1;
}
}
}

Exemplul 36: Un exemplu de for pe numere reale.

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

namespace Exemplul_36
{
class Program
{
static void Main(string[] args)
{
double rc, ic;
double x, y, z;
int n;
for (ic = 1.4; ic >= -1.4; ic -= 0.05)
{
for (rc = -0.7; rc <= 1.80; rc += 0.05)
{

43
n = 0;
x = ic * ic + rc * rc;
y = 2 * ic - 4 * rc;
z = x * x + y * y;
while (n <= 40 && z < 5)
{
x = ic * ic + rc * rc - rc;
y = 2 * ic - 4 * rc;
z = x * x - y * y;
n++;
}
switch (n % 4)
{
case 0: Console.Write("*"); break;
case 1: Console.Write("$"); break;
case 2: Console.Write("o"); break;
case 3: Console.Write("@"); break;
}
}
Console.WriteLine();
}
}
}
}

44
I.2.6.6. 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++) //afisarea vectorului v


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

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 = a[0];
f = 1;
for (i = 1; i < n; i++)
if (a[i] > max)
{
max = a[i];
f = 1;
}
else
if (a[i] == max) f++;
Console.WriteLine("Maximul din tablou este {0} cu frecventa {1}
", max, f);
}
}
}

56
Exemplul 47: 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 Efect
escape
\ apostrof
\ ghilimele
\\ backslash
\0 null
\a alarm
\b backspace
\f form feed pagin nou
\n new line linie nou
\r carriage return nceput de rnd
64
\t horizontal tab tab orizontal
\u caracter unicode
\v vertical tab tab vertical
\x caracter hexazecimal
I.2.8.1. Concatenarea irurilor de caractere

Pentru a concatena iruri de caractere folosim operatorul +

Exemplu:

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


//a este "Invat limbajul C#"

1.2.8.2. Compararea irurilor de caractere

Pentru a compara dou iruri de caractere vom utiliza operatorii == i !=.

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

namespace Exemplul_50
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul C#";
string b = "Invat " + "limbajul ";
b += "C#";
Console.WriteLine("a='{0}'", a);
Console.WriteLine("b='{0}'", b);
Console.WriteLine("a == b {0}", a == b);
Console.WriteLine("(object)a == b {0}", (object)a == b);
}
}
}

65
I.2.8.1. 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) Descrierea
string Concat(string u, string v) returneaz un nou ir obinut prin concatenarea
irurilor u i v
int IndexOf(char c) returneaz indicele primei apariii a caracterului
c n ir
int IndexOf(string s) returneaz indicele primei apariii a subirului s
string Insert(int a, string s) returneaz un nou ir obinut din cel iniial prin
inserarea n irul iniial, ncepnd cu poziia a,
a irului s
string Remove(int a, int b) returneaz un nou ir obinut din cel iniial prin
eliminarea, ncepnd cu poziia a, pe o lungime
de b caractere
string Replace(string u, string v) returneaz un nou ir obinut din cel iniial prin
prin nlocuirea subirului u cu irul v
string Split(char[] c) mparte un ir n funcie de delimitatorii c
string Substring(int index) returneaz un nou ir care este un subir al
irului ini ial ncepnd cu indicele index
string Substring(int a, int b) returneaz un nou ir care este un subir al
irului iniial, ncepnd de pe poziia a, pe
lungimea b caractere
string ToLower() returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la minuscule
string ToUpper() returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la majuscule
string Trim() returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la nceputul i
sfritul irului ini ial
string TrimEnd() returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la sfritul irului
ini ial
string TrimStart() 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_51
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul ";
string b = "C#";
string c;
Console.WriteLine("a = '{0}'", a);
Console.WriteLine("b = '{0}'", b);

67
c = string.Concat(a, b);
Console.WriteLine("string.Concat(a, b) = \"{0}\"", c);
Console.WriteLine("a.IndexOf(\"v\") = {0}",
Convert.ToString(a.IndexOf("v")));
Console.WriteLine("a.IndexOf(\"mba\") = {0}",
Convert.ToString(a.IndexOf("mba")));
Console.WriteLine("a.Insert(6, \"de zor \") = {0}", a.Insert(6,
"de zor "));
Console.WriteLine("a.Remove(5, 7) = {0}", a.Remove(5, 7));
Console.WriteLine("a.Replace(\"limbajul \", \"la informatica.\")
= {0}", a.Replace("limbajul ", "la informatica."));
Console.WriteLine("a.Substring(6) = {0}", a.Substring(6));
Console.WriteLine("a.Substring(10, 3) = {0}", a.Substring(10,
3));
Console.WriteLine("a.ToLower() = {0}", a.ToLower());
Console.WriteLine("a.ToUpper() = {0}", a.ToUpper());
string d = " Ana are mere. ";
Console.WriteLine("d = {0}", d);
Console.WriteLine("d.Trim() = {0}", d.Trim());
Console.WriteLine("d.TrimStart() = {0}", d.TrimStart());
}
}
}

Exemplul 52: Programul 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 System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Exemplul_56
{
class Program
{
static void Main(string[] args)
{
string[] a = { "primul", "fisier", "creat", "de mine", };
//deschiderea unui fisier si atasarea lui la un flux
StreamWriter outputFile = File.CreateText("C:\\C#\\fisier1.txt");

72
foreach (string b in a)
{
outputFile.WriteLine(b);//scrierea textului in fisier
}
//inchiderea fisierului
outputFile.Close();
//deschidem din nou fisierul de data aceasta pentru a citi din el
StreamReader inputFile = File.OpenText("C:\\C#\\fisier1.txt");
//definim o variabila string care va parcurge fisierul pana la
final
string x;
while ((x = inputFile.ReadLine()) != null)
{
System.Console.WriteLine(x);
}
//inchidem fisierul
inputFile.Close();
}

}
}

I.2.9.3. Scrierea i citirea datelor din 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) (date+date2)
subprog_1 subprog_1
subprog_2 subprog_2
subprog_3

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 date4
met1 met4

obiect3
obiect2 date3
met3
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
{ } corpul clasei Copil
Dac considerm clasa Copil ca i clas de baz,
putem deriva dou clase Fetia i Biat Fetita Baiat

public class Fetita: Copil { }


public sealed class Baiat: Copil { }

unde:
modificatorul sealed a fost folosit pentru a desemna faptul c nu se mai pot ob ine clase derivate
din clasa Baiat

I.4.2. Constructori

nainte de a continua amintim 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
public Copil ( ) //constructorul fara parametrii ai clasei
{
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) //constructor cu parametru


{
nume = s;
}
}
class Fetita : Copil
{
public Fetita(string s)
: base(s) //base semnifica faptul ca
{ //se face apel la
nume = "Fetita " + nume; //constructorul
//din clasa de baza
}
}

Fetita c = new Fetita();


Copil.adaug_copil(c);
//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 Explicaii
public 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 Explicaii
public 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 valoare
numeric 0
bool false
char \0
enum 0
referin 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, internal, private,
virtual, sealed, override, abstract, extern.

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

namespace Exemplul_77
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}

public void Afis()


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

public static Complex operator -(Complex c)


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

105
class Program
{
public static void Main()
{
Complex c1 = new Complex(10, 13);
c1.Afis();
Complex c2 = new Complex();
c2.Afis();
c2 = -c1;
c2.Afis();
Console.ReadLine();
}
}

Operatori binari

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

namespace ExempluOperatori
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void Afis()
{
Console.WriteLine("{0} {1}", x, y);
}

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


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

class Program
{
static void Main(string[] args)
{
Complex c1 = new Complex(1, 2);
Console.Write("c1: ");
c1.Afis();
Complex c2 = new Complex(3, 4);
Console.Write("c2: ");
c2.Afis();
Complex c3 = new Complex();
c3 = c1 + c2;
Console.WriteLine("\nc3 = c1 + c2\n");
Console.Write("c3: ");
c3.Afis();
Console.ReadLine();
}
}
}

Operatori de conversie

107
Operatorul de conversie introduce o conversie definit de utilizator. Aceast conversie nu va
suprascrie conversiile predefinite. Operatorii de conversie pot fi:
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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_79
{
class MyDigit
{
private int x;
public MyDigit()
{
}
public MyDigit(int i)
{
x = i;
}
public void ShowDigit()
{
Console.WriteLine("{0}", x);
}
public static implicit operator int(MyDigit md)
{
return md.x;
}
public static explicit operator MyDigit(int val)
{
return new MyDigit(val);
}
}

108
class Program
{
public static void Main(string[] args)
{
MyDigit md1 = new MyDigit(10);
int x = md1; //Implicit
Console.WriteLine(x);
int y = 25;
MyDigit md2 = (MyDigit)y; //Explicit
md2.ShowDigit();
Console.ReadLine();
}
}
}

Exemplul 80: Conversia dintr-un tip clas n altul folosind conversia operator:

109
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OperatoriImplicitiExpliciti
{
class Clasa1
{
public int x;
public Clasa1(int a)
{
x = a;
}
public void Afis1()
{
Console.WriteLine(x);
}
public static explicit operator Clasa2(Clasa1 mc1)
{
Clasa2 mc2 = new Clasa2(mc1.x * 10, mc1.x * 20);
return mc2;
}
}
class Clasa2
{
public float x, y;
public Clasa2(float a, float b)
{
x = a;
y = b;
}
public void Afis2()
{
Console.WriteLine(x);
Console.WriteLine(y);
}
}
class Program
{
public static void Main(string[] args)
{
Clasa1 mc1 = new Clasa1(100);
mc1.Afis1();
Clasa2 mc2 = (Clasa2)mc1;
mc2.Afis2();
Console.ReadLine();
}
}
}

110
I.6. Clase i 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_84
{
class Stiva
{
private object[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new object[MAX_SIZE]; }
public Object Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}

112
public void Push(Object item)
{
if (m_Index == MAX_SIZE)
throw new StackOverflowException("Nu se poate adauga un
elemet: stiva este plina.");
m_ItemsArray[m_Index++] = item;
}
}

class Program
{
static void Main(string[] args)
{
Stiva stiva = new Stiva();
stiva.Push(1234);
int numar = (int)stiva.Pop();
}
}
}

Implementarea sufer de 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_85
{
class Stiva<T>
{
private T[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new T[MAX_SIZE]; }
public T Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}
public void Push(Object item)
{
if (m_Index == MAX_SIZE)
throw new StackOverflowException("Nu se poate adauga un
elemet: stiva este plina.");
m_ItemsArray[m_Index++] = item;
}
}

class Program
{
static void Main(string[] args)
{
Stiva<int> stiva = new Stiva<T>();
stiva.Push(1234);
int numar = stiva.Pop(); //nu mai este necesar cast
Stiva<string> sstiva = new Stiva<string>();
sstiva.Push("4321");
string sNumar = sstiva.Pop();
}
}
}

I.7. Derivarea claselor (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) //constructor
{
this.var = var;
}
}

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 Bani

Imobiliara Bun Depunere Investiie Credit_primit

Teren B_inchiriat Actiune

Productiv Mobilier Cot

Neproductiv Altul Credit_acordat

Imobil VENIT
(din produse, din
De_folosin chirii, din dobnzi,
dividende)
calc()
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 Explicaii


sunt constructori
public Exception( )
public Exception (string)
public Exception (string, Exception) observm c o excep ie poate
conine n interiorul s o instan a
unei alte excepii
public virtual string HelpLink {get; set} obine sau seteaz o legtur ctre
fiierul Help asociat excepiei, sau
ctre o adres Web
public Exception InnerException {get;} returneaz excepia care este
ncorporat n excepia curent
public virtual string Message {get;} obine un mesaj care descrie excepia
curent
public virtual string Source {get; set;} obine sau seteaz numele aplicaiei
sau al obiectului care a cauzat
eroarea
public virtual string StackTrace {get;} obine o reprezentare de tip string a
apelurilor de metode care au dus la
apariia excepiei
public MethodBase TargetSite {get;} 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
ArrayTypeMismatchException Incompatibilitate ntre tipul valorii
memorate i tipul tabloului
DivideByZeroException ncercare de mprire la zero
IndexOutOfRangeException Indexul tabloului depete marginile
definite
InvalidCastException Operatorul cast incorect la execuie
OutOfMemoryException Datorit memoriei insuficiente apelul
lui new eueaz
OverflowException 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. n
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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exceptii1
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("Introduceti un numar ");
int i = int.Parse(Console.ReadLine());
Console.Write("Introduceti inca un numar ");
int j = int.Parse(Console.ReadLine());
int x = i / j;
}
catch (OverflowException e)
{
Console.WriteLine("Numarul nu este intreg"); //(1)
//Console.WriteLine(e); //(2)
}

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

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

namespace Exemplul_93
{
class Program
{
static void F(params int[] arg)
{
Console.WriteLine("Apelul functiei F cu {0} parametri:",
arg.Length);
for (int i = 0; i < arg.Length; i++)
{
Console.WriteLine("arg[{0}] = {1}", i, arg[i]);
}
Console.WriteLine("");
}
static void Main(string[] args)
{
F();
F(2);
F(4, 6);
F(new int[] { 1, 2, 3 });
}
}
}

127
I.9.3. Polimorfismul ad-hoc

Acest tip de polimorfism se mai 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PolimorfismAdHoc
{
class Program
{
static void F()
{
Console.WriteLine("Functia F fara parametri\n");
}
static void F(int a, int b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
int\n");
}
static void F(int a, double b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
float\n");
}
static void Main(string[] args)
{
F();
F(2, 3);
F(4, 6.3);
}
}
}

128
I.9.4. Polimorfismul de 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exemplul_95
{
class Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}

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

namespace Exemplul_96
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public override void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}

130
I.9.6. Modificatorul new

n cazul n care se 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PolimorfismDeMostenire
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public new void Afis() // !!! new
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
}
}
}

131
I.9.7. Metoda sealed

O metod 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 clasa de baza\n");
}
}
class Derivata : Baza
{
sealed override public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Derivata2 : Derivata
{
override public void Afis() //!!! EROARE !!!
{
Console.WriteLine("Apelul functiei Afis din clasa Derivata2\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = new Derivata();
Derivata2 obiect3 = new Derivata2();
obiect1.Afis(); //(1)
obiect2.Afis(); //(2)
obiect3.Afis();

}
}

132
Va genera eroare, deoarece modificatorul sealed al metodei Afis(), din clasa Derivata, va
mpiedic suprascrierea acestei metode n clasa Derivata2.

II. Programare vizual

II.1. Concepte de baz ale 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 Fereastra Solution
Form1 Explorer

Fereastra pentru Fereastra Properties


afiarearea Listei de
erori

Bara de unelte 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 s


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 o ferestr
corespunztoare codului dorit.
Acelai lucru l putem spune i 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 sunt obiecte de clase derivate din clasa
System.Windows.Forms.Control. Datorit acestui fapt multe dintre proprietile i

141
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 Descrierea proprietii


Anchor se refer la posibilitatea de a ancora controlul fa de o margine (sau
toate)
BackColor permite stabilirea culorii de fundal a controlului
Bottom permite stabilirea distanei dintre marginea de sus a ferestrei i control
Dock ataeaz controlul la una dintre marginile ferestrei
Enabled permite controlului s recepioneze evenimente de la utilizator
ForeColor permite stabilirea culorii textului
Height permite definirea nlimii controlului
Left permite stabilirea distanei dintre marginea din stnga a ferestrei i
marginea stnga a controlului
Name permite denumirea controlului pentru a-l putea mai uor vizualiza i
manipula n codul surs
Parent printele controlului
Right permite stabilirea distanei dintre marginea din dreapta a ferestrei i
marginea din dreapta a controlului
TabIndex prin numrul de ordine care i se ataeaz se stabilete ordinea activrii
controlului la apsarea tastei TAB
TabStop permite sau nu ca respectivul control s fie activat prin apsarea tastei
TAB
Tag se refer la un ir de caractere pe care controlul l poate stoca n interiorul
su
Top permite stabilirea distanei dintre marginea de sus a ferestrei i marginea
de sus a controlului
Visible stabilete dac respectivul control, care exit n fereastr, este (TRUE)
sau nu vizibil
Width 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 Descrierea evenimentului


Clic se genereaz cnd se d clic asupra unui control
DoubleClic 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
DragDrop se genereazla finalizarea lui drag and drop

142
Evenimentul Descrierea evenimentului
DragEnter se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge n
interiorul controlului
DragLeave se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge s
prseasc controlului
DragOver se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge
deasupra controlului
KeyDown 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
KeyPress 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
KeyUp se genereaz cnd o tast este eliberat n timp ce controlul este activ.
Se genereaz dup KeyDown i KeyPress
GotFocus se genereaz cnd controlul devine activ (se mai spune: cnd controlul
primete input focusul)
LostFocus se genereaz cnd controlul devine inactiv (se mai spune: cnd controlul
pierde input focusul)
MouseDown se genereaz cnd cursorul mouse-ului este deasupra controlului i se
apas un buton al mouse-ului
MouseMove se genereaz cnd trecem cu mouse-ul deasupra controlului
MouseUp se geereaz cnd mouse-ul este deasupra controlului i eliberm un
buton al mouse-ului
Paint se genereaz la desenarea controlului
Validated se genereaz cnd un control este pe cale s devin activ. Se genereaz
dup terminarea evenimentului Validating, indicnd faptul c validarea
controlului este complet
Validating se genereaz cnd un control este pe cale s devin activ

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 stabilindu-
se direct :

public Form Owner { get; set; }


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

Formularul deschis modal va avea un proprietar setat pe null. 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 i 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 Numele Descriere


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

II.5. 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 controalelor de selecie CheckBox i RadioButton.


Propietatea Checked 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
i

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-Items-
Collection), butonul Selecie i ListBox-ul.
Evenimentul Click asociat butonului Selectie golete mai nti listBox-ul
(listBox1.Items.Clear();) 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", Prenume = "Prenume 1",
Nota = 9 });
elevi.Add(new Elev() { Nume = "Nume 2", Prenume = "Prenume 2",
Nota = 10 });
elevi.Add(new Elev() { Nume = "Nume 3", Prenume = "Prenume 3",
Nota = 8 });
elevi.Add(new Elev() { Nume = "Nume 4", Prenume = "Prenume 4",
Nota = 9 });
return elevi;
}
}

165
Proiectul nostru con ine i un Form unde am aezat un control de tip ListView. Codul din
Form1.cs este acesta:
public Form1()
{
InitializeComponent();
SeteazaLista();
}
private void SeteazaLista()
{
listViewTest.Columns.Add("Nume", 200, HorizontalAlignment.Left);
listViewTest.Columns.Add("Prenume", 200,
HorizontalAlignment.Left);
listViewTest.Columns.Add("Nota", 200, HorizontalAlignment.Left);
listViewTest.View = View.Details;
listViewTest.Sorting = SortOrder.Ascending;
listViewTest.AllowColumnReorder = true;
}
private void Form1_Load(object sender, EventArgs e)
{
this.listViewTest.BeginUpdate();
ListViewItem lvi;
ListViewItem.ListViewSubItem lvsi;
foreach (Elev elev in Elev.CitesteElevi())
{
lvi = new ListViewItem();
lvi.Text = elev.Nume;
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = elev.Prenume;
lvi.SubItems.Add(lvsi);
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = elev.Nota.ToString();
lvi.SubItems.Add(lvsi);
listViewTest.Items.Add(lvi);
}
this.listViewTest.EndUpdate();
}
}

Metoda SeteazaLista 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 a 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 care permite
reprezentri grafice. De exemplu, o linie frnt se poate realiza astfel:

172
Point[] points = new Point[4];
points[0] = new Point(0, 0);points[1] = new Point(0, 120);
points[2] = new Point(20, 120);points[3] = new Point(20, 0);
Graphics g = this.CreateGraphics();
Pen pen = new Pen(Color.Yellow, 2);g.DrawLines(pen, points);

Exemplul 19: Desen

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 System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Interfata3
{
public partial class Form1 : Form
{
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr Handle, int Msg,
int Param1, int Param2);

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)


{
this.Close();
}

private void pictureBox1_MouseDown(object sender,


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

Revenim n fereastra Form1.cs[Designer], 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 Valoare Explicaie


(Name) aplCeas

Enabled True Activarea controlului de timp


Interval 1.000 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 Proprietate Valoare


label1 (Name) labelCeas
AutoSize False
BorderStyle Fixed3D
FontSize 16,25, Bold
Location 82;112
192
Text
Size 129;42
TextAlign 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 i 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=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial
Catalog=SALARII;IntegratedSecurity=SSPI");
Sau implicit :

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

ConnectionString (String, cu accesori de tip get i set ) 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=DANA-


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

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

Exemplul 5: Se obine coninutul tabelei ntr-un obiect de tip SqlDataReader.

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


D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM SALAR_ANGAJAT", co);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
Console.WriteLine(String.Format("\t{0}\t{1}\t{2} \t {3} \t {4}",
reader[0],reader[1],reader[2],reader[3],reader[4]));
Console.ReadLine();
reader.Close();

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

De data aceasta vom afia coninutul ambelor tabele.


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

Metoda ExecuteReader() mai are un argument 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=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr[1]); }
rdr.Close();
Console.ReadLine();

sau
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr["nume"]); }
rdr.Close();
Console.ReadLine();

ExecuteScalar() execut comanda i returneaz valoarea primei coloane de pe primul 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=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM SALAR_ANGAJAT",co);
var=(Int32) cmd.ExecuteScalar();
Console.WriteLine(var);
Console.ReadLine();

II.8.7. Interogarea datelor

Pentru extragerea datelor cu ajutorul unui obiect SqlCommand trebuie s 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=DANA-


D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
try
{co.Open();
string insertString = @"insert into salar_angajat(ID ,NUME ,PRENUME
,VECHIME ,SALAR)values (6,'BARBU','EUGENIU',17,1993)";
SqlCommand cmd = new SqlCommand(insertString, co);
cmd.ExecuteNonQuery();}
finally
{if (co != null) { co.Close(); }}
SqlCommand comand = new SqlCommand("SELECT * FROM SALAR_ANGAJAT", co);
co.Open();
SqlDataReader reader = comand.ExecuteReader();
while (reader.Read())
Console.WriteLine(String.Format("\t{0}\t{1}\t{2} \t {3} \t {4}",
reader[0], reader[1], reader[2], reader[3], reader[4]));
Console.ReadLine();
reader.Close(); }

II.8.9. Actualizarea datelor

Exemplul 10: vom modifica numele unui angajat, din BARBU n BIBIRE n tabela
SALAR_ANGAJAT i vom afia tot coninutul tabelei
SqlConnection co = new SqlConnection("DATA SOURCE=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
string updateString = @"update SALAR_ANGAJAT set NUME = 'BIBIRE' where
NUME = 'BARBU'";
SqlCommand cmd = new SqlCommand(updateString);
cmd.Connection = co; // Stabilim conexiunea
cmd.ExecuteNonQuery();//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=DANA-


D90FDEF1A8\\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=DANA-
D90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand comand1 = new SqlCommand("select MAX(VECHIME) FROM
SALAR_ANGAJAT",co);
var = (Int32)comand1.ExecuteScalar();
Console.Write(" CEA MAI MARE VECHIME A UNUI ANGAJAT ESTE DE :");
Console.Write(var); Console.WriteLine(" ANI");
SqlCommand comand2 = new SqlCommand("select SUM(SALAR) FROM
SALAR_ANGAJAT", co);
suma = (Int32)comand2.ExecuteScalar();
Console.Write(" SUMA SALARIILOR TUTUROR ANGAJATILOE ESTE: ");
Console.Write(suma); Console.WriteLine(" RON");
Console.ReadLine();

220
Exemplul 12: 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=DANA-
D90FDEF1A8\\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 n datasetul ds sub forma unei
tabele locale numite salariu_angajat
SqlDataAdapter dp=new SqlDataAdapter("SELECT nume,telefon FROM telefoane,conn);
dp.Fill(ds," telefoane ");//transfer datele n datasetul ds sub forma unei tabele
locale numite telefoane
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;
DataTable este compus la rndul lui 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 Source=DANA-
D90FDEF1A8\SQLEXPRESS;Database=dana;Trusted_Connection=yes;");
co.Open();
}
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 l-
am 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