Documente Academic
Documente Profesional
Documente Cultură
Manual C# Oop Si Vizual
Manual C# Oop Si Vizual
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
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),
o bibliotec de clase pentru crearea serviciilor Web, aplicaiilor Web i aplicaiilor desktop
Windows.
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 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
I.1.1.
Servicii WEB
Formulare
FCL
CLR
Componenta .NET Framework este format din compilatoare, biblioteci i alte executabile utile
n rularea aplicaiilor .NET. Fiierele corespunztoare se afl, n general, n directorul
C:\WINDOWS\Microsoft. NET\Framework\V2.0. (corespunztor versiunii instalate)
I.1.2.
Compilarea programelor
Un program scris ntr-unul dintre limbajele .NET conform Common Language Specification
(CLS) este compilat n Microsoft Intermediate Language (MSIL sau IL). Codul astfel obinut are
extensia "exe", dar nu este direct executabil, ci respect formatul unic MSIL.
CLR include o main virtual asemntoare cu o main Java, ce execut instruciunile IL
rezultate n urma compilrii. Maina folosete un compilator special JIT (Just In Time).
Compilatorul JIT analizeaz codul IL corespunztor apelului unei metode i produce codul main
adecvat i eficient. El recunoate secvenele de cod pentru care s-a obinut deja codul main
adecvat, permind reutilizarea acestuia fr recompilare, ceea ce face ca, pe parcursul rulrii,
aplicaiile .NET s fie din ce n ce mai rapide.
Faptul c programul IL produs de diferitele limbaje este foarte asemntor are ca rezultat
interoperabilitatea ntre aceste limbaje. Astfel, clasele i obiectele create ntr-un limbaj specific
.NET pot fi utilizate cu succes n altul.
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
direct la memorie folosind pointeri) au fost pstrate, dar secvenele de cod corespunztoare se
consider nesigure.
I.2.2.
Pentru a realiza aplicaii consol (ca i cele din Borland Pascal sau Borland C) n mediul de
dezvoltare Visual Studio, trebuie s instalm o versiune a acestuia, eventual mediul free Microsoft
Visual C# 2008 Express Edition de la adresa http://www.microsoft.com/express/download/
Dup lansarea aplicaiei, din meniul File se alege opiunea NewProject apoi alegem
ConsoleApplication, modificnd numele aplicaiei n caseta Name.
Cnd creai o aplicaie consol, se genereaz un fiier cu extensia .cs. n cazul nostru, s-a
generat fiierul Primul.cs. Extensia cs provine de la C Sharp. Redenumirea lui se poate realiza
din fereastra Solution Explorer, pe care o putei afia cu ajutorul combinaiei de taste Ctrl+W,S
sau din meniul View.
Codul surs generat este :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
}
}
}
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:
I.2.3.
using System;
namespace HelloWorld
{
class Program
{
static void Main()
{
Console.WriteLine("Hello World!");
}
}
}
O aplicaie C#
este format din una sau mai multe clase, grupate n spaii de nume
(namespaces). Este obligatoriu ca doar una din aceste clase s conin un punct de intrare
(entry point), i anume metoda (funcia) Main.
class
claselor,
aflate
metod
interiorul
namespaces-urilor.
Convenie:
cod
S-a
adoptat
urmtoarea
scris
cu
majuscul:
HelloWorld,
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 */
Nepropunndu-ne s intrm n
I.2.4.2. Nume
Definiie: Prin nume dat unei variabile, clase, metode etc. nelegem o succesiune de
caractere care ndeplinete urmtoarele reguli:
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).
n cazul numelor variabilelor, dac numele este compus din mai multe cuvinte, primul
ncepe cu minuscul, celelalte cu majuscul.
as
case
const
do
explicit
float
implicit
is
null
params
ref
sizeof
switch
typeof
ushort
while
base
catch
continue
double
extern
for
in
lock
object
private
return
stackalloc
this
uint
using
bool
char
decimal
else
false
foreach
int
long
operator
protected
sbyte
static
throw
ulong
virtual
break
checked
default
enum
finally
goto
interface
namespace
out
public
sealed
string
true
unchecked
void
ascending
get
on
value
by
group
orderby
where
descending
into
partial
yield
equals
join
select
from
let
set
11
I.2.4.3. Constante
n C# exist dou modaliti de declarare a constantelor: folosind const sau folosind
modificatorul readonly. Constantele declarate cu const trebuie s fie iniializate la declararea
lor.
Exemplul 1:
const int x;
const int x = 13;
Constantele declarate cu ajutorul lui readonly sunt doar variabilele membre ale claselor,
ele putnd fi iniializate doar de ctre constructorii claselor respective.
Exemplul 2:
readonly int x;
readonly int x = 13;
//corect
//corect
I.2.4.4. Variabile
O variabil n C# poate s conin fie o valoare a unui tip elementar, fie o referin la un
obiect. C# este case sensitive, deci face distincie ntre litere mari i mici.
Exemplul 3:
int Salut;
int Azi_si_maine;
char caracter;
Ternari: - acioneaz asupra a trei operanzi; exist un singur operator ternar i acesta
este ?:
n C# sunt definii mai muli operatori. n cazul n care ntr-o expresie nu intervin paranteze,
operaiile se execut conform prioritii operatorilor. n cazul n care sunt mai muli operatori cu
aceeai prioritate, evaluarea expresiei se realizeaz de la stnga la dreapta. n tabelul alturat
prioritatea descrete de la 0 la 13.
Tabelul de prioriti:
Prioritate
0
1
2
3
4
5
6
7
8
9
10
11
12
13
Tip
Primar
Unar
Multiplicativ
Aditiv
De deplasare
Relaional
De egalitate
AND (SI) logic
XOR (SAU exclusiv)
logic
OR (SAU) logic
AND (SI)
condiional
OR (SAU)
condiional
Condiional(ternar)
atribuire simpl
atribuire compus
Operatori
( ) [ ] f() . x++ x-- new typeof sizeof
checked unchecked ->
+ - ! ~ ++x --x (tip) true false & sizeof
* / %
+ << >>
< > <= >= is as
== !=
&
^
Asociativitate
|
&&
||
?:
=
*= /= %= += -= ^= &= <<= >>=
|=
Exemplul 4: folosind operatorul ternar ?:, s se decid dac un numr citit de la tastatur este
pozitiv sau negativ.
Indicaii:
13
using System;
using System.Collections.Generic;
using System.Text;
namespace OperatorConditional
{
class Program
{
static void Main(string[] args)
{
int a;
string rezultat;
a = int.Parse(Console.ReadLine());
Console.Write(a);
rezultat = (a > 0) ? " este nr. pozitiv" : " este nr. negativ";
Console.Write(rezultat);
Console.ReadLine();
}
}
}
Exemplul 5: Folosind operatorul %, s se verifice dac un numr este par sau impar. Observaie:
Convert.ToInt32 convertete un ir la Int32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace primul_proiect
{
class Program
{
static void Main(string[] args)
{
int x;
x = Convert.ToInt32(Console.ReadLine());
if (x % 2 == 0) Console.WriteLine("este par");
else System.Console.WriteLine("este impar");
}
}
}
14
Exemplul 6: Urmtorul program afieaz la consol tabelul de adevr pentru operatorul logic &.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_6
{
class Program
{
static void Main(string[] args)
{
bool v1, v2;
v1 = true; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
v1 = true; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
v1 = false; v2 = true;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
v1 = false; v2 = false;
Console.WriteLine("{0,6}" + " & " + "{0,6}" + " = "
v1,
Console.ReadKey();
}
}
}
+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);
+ "{0,6}",
v2, v1 & v2);
15
Exemplul 7:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_7
{
class Program
{
static void Main(string[] args)
{
int a, b, c = 5;
a = c++;
b = ++c;
Console.WriteLine("a={0} b={1}", a,b);
}
}
}
Exemplul 8: n acest exemplu, formatul de afiare ales #.### va produce afiarea cu trei
zecimale a constantei PI
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_8
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Valoarea constantei matematice PI este
{0:#.###}",Math.PI);
}
}
}
16
I.2.4.8. Conversii
n C# exist dou tipuri de conversii numerice:
implicite
explicite.
Conversia implicit se efectueaz (automat) doar dac nu este afectat valoarea convertit.
Exemplul 9: Exemplul urmtor realizeaz suma a dou valori numerice fr semn cu reprezentare
pe 8 bii. Rezultatul va fi reinut pe 64 bii
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_9
{
class Program
{
static void Main(string[] args)
{
byte a = 13; // byte intreg fara semn pe 8 bii
byte b = 20;
long c;
// intreg cu semn pe 64 bii
c = a + b;
Console.WriteLine("{0} + {1} = {2}", a, b, c);
Console.WriteLine("Suma intregilor pe 8 bii se reprezinta pe 64
bii");
}
}
}
17
n
short, int, long, float, double, decimal
short, ushort, int, uint, long, ulong, float, double, decimal
int, long, float, double, decimal
int, uint, long, ulong, float, double, decimal
long, float, double, decimal
long, ulong, float, double, decimal
float, double, decimal
ushort, int, uint, long, ulong, float, double, decimal
double
float, double, decimal
din
sbyte
byte
sbyte, char
short
ushort
int
uint
long
ulong
char
float
sbyte, byte, short, ushort, int, uint, long, ulong, char, decimal
double
sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
decimal
decimal
sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double
18
Exemplul 10:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_10
{
class Program
{
static void Main(string[] args)
{
int a = 5;
int b = 2;
float c;
c = (float)a / b; //operatorul cast
Console.WriteLine("{0} / {1} = {2}", a, b, c);
Console.WriteLine("Catul intregilor, reprezentat ca real datorita
operatorului cast\nde conversie explicita");
}
}
}
n cazul n care nu s-ar fi folosit operatorul cast, rezultatul - evident eronat - ar fi fost:
Des ntlnit este conversia din tipul numeric n ir de caractere i reciproc. Conversia din
tipul numeric n ir de caractere se realizeaz cu metoda ToString a clasei Object
Exemplul 11:
int i = 13
string j = i.ToString();
19
Conversia din ir de caractere n numr se realizeaz cu ajutorul metodei Parse tot din
clasa Object.
Exemplul 12:
string s = "13";
int n = int.Parse(s);
Exemplul 13: Exemplul de mai jos prezint mai multe tipuri de conversii
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_13
{
class Program
{
static void Main(string[] args)
{
short srez, sv = 13;
int iv = 123;
long lrez;
float frez, fv = 13.47F;
double drez, dv = 87.86;
string strrez, strv = "15";
bool bv = false;
Console.WriteLine("Exemple de conversii:\n");
Console.WriteLine("Implicite:");
drez = fv + sv;
Console.WriteLine("float si short spre double {0} + {1} = {2}",
fv, sv, drez);
frez = iv + sv;
Console.WriteLine("int si short spre float {0} + {1} = {2}\n",
iv, sv, frez);
fv, srez);
Console.WriteLine("Explicite:");
srez = (short)fv;
Console.WriteLine("float spre short folosind cast {0} spre {1}",
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
stiva
13
int i=13;
ob
object ob=i;
21
heap
int
13
Se poate determina tipul pentru care s-a fcut mpachetarea folosind operatorul is:
Exemplul 15:
int i = 13;
object ob = i;
if (ob is int)
{
Console.WriteLine("Impachetarea s-a facut pentru int");
}
Exemplul 17: Prin conversia de tip unboxing, obiectul ob poate fi asignat variabilei ntregi i:
int i = 13;
object ob = i;
i = (int)ob;
//boxing implicit
//unboxing explicit
22
+ numr
int
long
double
float
Exemplul 18:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_18
{
class Program
{
static void Main(string[] args)
{
string s;
const int a = 13;
const long b = 100000;
const float c = 2.15F;
double d = 3.1415;
Console.WriteLine("CONVERSII\n");
Console.WriteLine("TIP\tVAL. \tSTRING");
Console.WriteLine("----------------------");
s = "" + a;
Console.WriteLine("int\t{0} \t{1}", a, s);
s = "" + b;
Console.WriteLine("long\t{0} \t{1}", b, s);
s = "" + c;
Console.WriteLine("float\t{0} \t{1}", c, s);
s = "" + d;
Console.WriteLine("double\t{0} \t{1}", d, s);
Console.WriteLine("\nSTRING\tVAL \tTIP");
Console.WriteLine("----------------------");
int a1;
a1 = int.Parse("13");
23
}
}
tipuri valoare
-
tipuri referin
-
using System;
using System.Collections.Generic;
using System.Text;
namespace ExempluTipuriValoare
{
public struct Intreg
{
public int v;
}
class Program
{
static void Main(string[] args)
{
Intreg sa = new Intreg();
sa.v = 13;
Intreg sb = sa;
// se initializeaza prin copiere variabila sb
Console.WriteLine("sa.v este {0}.", sa.v);
Console.WriteLine("sb.v este {0} prin initializare.", sb.v);
sa.v = 10;
Console.WriteLine("sa.v este {0}.", sa.v);
Console.WriteLine("sb.v este {0}.", sb.v);
Console.ReadLine();
}
}
}
Spre deosebire de tipurile valoare, pentru tipurile referin, declararea unei variabile nu
implic automat alocarea de spaiu: iniial, referin ele sunt null i trebuie alocat explicit
memorie pentru obiectele propriu-zise. n plus, la atribuire, este copiat referina n variabila
25
destinaie, dar obiectul spre care indic rmne acelai (aliasing). Aceste reguli poarta
denumirea de reference semantics.
Exemplul 20: Pentru exemplificarea celor de mai sus, pentru tipurile referin, vom folosi clasa
StringBuilder.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace ExempluTipuriReferinta
{
class Program
{
static void Main(string[] args)
{
StringBuilder a = new StringBuilder();
StringBuilder b = a;
a.Append("Salut");
Console.WriteLine("a este '{0}'.", a);
Console.WriteLine("b este '{0}' prin initializare.", b);
a = null;
Console.WriteLine("a este '{0}' prin atribuirea unei noi
valori.", a);
Console.WriteLine("b este '{0}'.", b);
Console.ReadLine();
}
}
}
26
Descriere
System.String
System.Sbyte
System.Int16
System.Int32
System.Int64
System.Byte
System.Int16
System.Uint32
System.Uint64
System.Single
System.Double
System.Boolean
System.Char
System.Decimal
Domeniul de valori
-128; 127
-32768; 32767
-2147483648; 2147483647
-9223372036854775808; 9223372036854775807
0; 255
0; 65535
0; 4294967295
0; 18446744073709551615
-3.402823E+38; 3.402823E+38
-1.79769313486232E+308; 1.79769313486232E+308
-79228162514264337593543950335;
79228162514264337593543950335
Tip
int, uint, long, ulong
uint, ulong
long, ulong
ulong
27
Exemplul 21:
string s = Salut!
long a = 10;
long b = 13L;
ulong c = 12;
ulong d = 15U;
ulong e = 16L;
ulong f = 17UL;
float g = 1.234F;
double h = 1.234;
double i = 1.234D;
bool cond1 = true;
bool cond2 = false;
decimal j = 1.234M;
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
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();
}
}
}
"
C#
exist
astfel
de
posibilitate,
folosind
este echivalent cu
T? var;
structura
System.Nullable<T>.
proprietate HasValue, care indic dac valoarea intern este diferit sau nu de null
a ?? b
cu semnificaia: dac a este null b este evaluat i constituie rezultatul expresiei, altfel
rezultatul este a.
I.2.6.1. Instruciunea if
Instruciunea if are sintaxa:
if (conditie)
Instructiuni_A;
else
Instructiuni_B;
Exemplul 23: Citindu-se dou numere ntregi, s se decid care dintre ele este mai mare
using System;
namespace Exemplul_23
{
class Program
{
static void Main(string[] args)
{
int a, b;
string rezultat;
Console.Write("Dati primul numar intreg : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati al doilea numar intreg : ");
b = Convert.ToInt32(Console.ReadLine());
if (a > b) rezultat = "primul este mai mare";
else
if (a < b) rezultat = "primul este mai mic";
else rezultat = "numere egale";
Console.WriteLine("Rezultatul comparatiei lui {0} cu {1} este
\"{2}\"", a, b, rezultat);
}
}
}
30
Exemplul 24: S se verifice dac 3 puncte din plan M1, M2 i M3, date prin coordonatele lor ntregi,
sunt coliniare.
Punctele M1(x1,y1), M2(x2,y2), M3(x3,y3) sunt coliniare
x1
x2
x3
y1 1
y2 1 = 0
y3 1
E=(x2-x1)(y3-y1)-(x3-x1)(y2-y1)=0
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_24
{
class Program
{
static void Main(string[] args)
{
double x1, y1, x2, y2, x3, y3;
Console.WriteLine("Coordonatele primului punct:");
Console.Write("Abscisa : ");
x1 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y1 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al doilea punct:");
Console.Write("Abscisa : ");
x2 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y2 = Convert.ToDouble(System.Console.ReadLine());
Console.WriteLine("Coordonatele celui de-al treilea punct:");
Console.Write("Abscisa : ");
x3 = Convert.ToDouble(System.Console.ReadLine());
Console.Write("Ordonata : ");
y3 = Convert.ToDouble(System.Console.ReadLine());
double E = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
if (E == 0) Console.WriteLine("Puncte coliniare");
else Console.WriteLine("Puncte necoliniare");
31
Exemplul 25: S se verifice dac un numr ntreg x este ntr-un interval dat [a, b]
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_25
{
class Program
{
static void Main(string[] args)
{
int a, b, x;
Console.WriteLine("Se citesc doua numere care vor reprezenta
capetele intervalului");
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
if (a > b)
{
x = a;
a = b;
b = x;
} // interschimbarea valorilor pentru a avea intervalul [a, b]
Console.Write("x = ");
x = Convert.ToInt32(Console.ReadLine());
if (x >= a && x <= b)
Console.WriteLine("Numarul {0} este in intervalul [ {1}, {2}
]", x, a, b);
else
Console.WriteLine("Numarul {0} nu este in intervalul [ {1},
{2} ]", x, a, b);
}
}
}
32
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_26
{
class Program
{
static void Main(string[] args)
{
int x, n, k, ux;
Console.Write("Dati un numar natural ca baza a puterii : ");
x = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati un numar natural ca exponent al puterii : ");
n = Convert.ToInt32(Console.ReadLine());
ux = x % 10; // ma intereseaza doar ultima cifra
Console.Write("Ultima cifra a lui {0} la puterea {1} este : ", x,
n);
if (n == 0) Console.WriteLine(" 1 ");
else
switch (ux)
{
case 0: Console.WriteLine(" 0 "); break;
case 1: Console.WriteLine(" 1 "); break;
case 2:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 ");
case 1: Console.WriteLine(" 2 ");
case 2: Console.WriteLine(" 4 ");
case 3: Console.WriteLine(" 8 ");
}
break;
33
break;
break;
break;
break;
case 3:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 ");
case 1: Console.WriteLine(" 3 ");
case 2: Console.WriteLine(" 9 ");
case 3: Console.WriteLine(" 7 ");
}
break;
case 4:
if (n % 2 == 0) Console.WriteLine(" 6
else Console.WriteLine(" 4 ");
break;
case 5:
Console.WriteLine(" 5 ");
break;
case 6:
Console.WriteLine(" 6 ");
break;
case 7:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 1 ");
case 1: Console.WriteLine(" 7 ");
case 2: Console.WriteLine(" 9 ");
case 3: Console.WriteLine(" 3 ");
}
break;
case 8:
k = n % 4;
switch (k)
{
case 0: Console.WriteLine(" 6 ");
case 1: Console.WriteLine(" 8 ");
case 2: Console.WriteLine(" 4 ");
case 3: Console.WriteLine(" 2 ");
}
break;
case 9:
if (n % 2 == 0) Console.WriteLine(" 1
else Console.WriteLine(" 9 ");
break;
}
}
}
using
using
using
using
}
System;
System.Collections.Generic;
System.Linq;
System.Text;
34
break;
break;
break;
break;
");
break;
break;
break;
break;
break;
break;
break;
break;
");
Exemplul 27: Programul urmtor efectueaz calculele corespunztoare pentru dou numere ntregi
i unul dintre semnele +,-,*,/ , % introduse de la tastatur
namespace Exemplul_27
{
class Program
{
static void Main(string[] args)
{
char op;
int a, b;
Console.WriteLine("Exemplu pentru operatori aritmetici");
Console.Write("Dati primul numar intreg
: ");
a = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati al doilea numar intreg : ");
b = Convert.ToInt32(Console.ReadLine());
Console.Write("Dati simbolul unui operator aritmetic : ");
op = (char)Console.Read();
switch (op)
{
case '+': Console.WriteLine("Adunare
: {0} + {1} = {2}", a,
b, a + b);
break;
case '-': Console.WriteLine("Scadere
: {0} - {1} = {2}", a,
b, a - b);
break;
case '*': Console.WriteLine("Inmultire : {0} * {1} = {2}", a,
b, a * b);
break;
case '/': Console.WriteLine("Impartire : {0} / {1} = {2}", a,
b, (float)a / b);
break;
case '%': Console.WriteLine("Modulo
: {0} % {1} = {2}", a,
b, a % b);
break;
default: Console.WriteLine("Simbolul nu reprezinta o operatie
aritmetica");
break;
}
}
}
}
35
using System;
namespace Exemplul_28
{
class Program
{
static void Main(string[] args)
{
int n = 0;
while (n <= 10)
{
Console.Write("{0,3}", n);
n++;
}
Console.ReadLine();
}
}
}
36
Exemplul 29: Programul de mai jos numr cte cifre pare are un numr natural:
using System;
namespace Exemplul_29
{
class Program
{
static void Main(string[] args)
{
uint a = 1223466, b;
b = CateCifrePare(a);
Console.WriteLine("Numarul {0} are {1} cifre pare", a, b);
}
static uint CateCifrePare(uint a)
{
uint k = 0;
if (a == 0) k = 1;
while (a != 0)
{
if (a % 10 % 2 == 0) k++; // sau if(a % 2 == 0)
// pentru ca a numar par daca si numai daca ultima cifra este
para
a = a / 10;
}
return k;
}
}
}
Exemplul 30: S se calculeze cmmdc i cmmmc pentru dou numere citite de la tastatur.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_30
{
class Program
{
static void Main(string[] args)
{
int a, b, r, x, y;
Console.Write("Dati primul numar : ");
a = Convert.ToInt32(Console.ReadLine());
37
x = a;
y = b;
r = x % y;
while (r != 0)
{
x = y;
y = r;
r = x % y;
}
if (y != 1)
Console.WriteLine("Cmmdc ({0}, {1}) = {2} ", a, b, y);
else
Console.WriteLine("{0} si {1} sunt prime intre ele ", a, b);
Console.WriteLine("Cmmmc ({0}, {1}) = {2}", a, b, a / y * b);
Console.ReadKey();
}
Exemplul 31: Dintr-un numr ntreg pozitiv, citit de la tastatur, s se elimine cifra cea mai mic i
s se afieze numrul rezultat n urma acestei operaii.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_31
{
class Program
{
static void Main(string[] args)
{
uint n, min, v;
Console.Write("Dati un numar intreg pozitiv : ");
n = Convert.ToUInt32(Console.ReadLine());
min = MinCifra(n);
v = Valoare(n, min);
Console.WriteLine("Eliminand cifra minima {0} din {1} obtinem
{2}", min, n, v);
}
38
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();
}
}
}
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_33
{
class Program
{
static void Main(string[] args)
{
int x, n, k = 0;
do
{
Console.Write("Dati un numar natural : ");
n = Convert.ToInt32(Console.ReadLine());
if (n <= 0)
Console.WriteLine("Eroare la citire!");
} while (n <= 0);
Console.Write("Numerele palindroame mai mici strict decat {0}
sunt :\n", n);
x = 1;
40
do
{
if (palindrom(x) == 1)
{
Console.Write(" {0,3} ", x);
k++;
}
x++;
} while (x < n);
Console.WriteLine();
if (k == 0) Console.WriteLine("Nu exista numere!");
else Console.WriteLine("Sunt {0} numere palindroame!", k);
}
static uint palindrom(int x)
{
int y = 0, z = x;
do
{
y = y * 10 + z % 10;
z /= 10;
} while (z != 0);
if (y == x) return 1;
else return 0;
}
}
41
Exemplul 35: S se determine numerele prime, precum i numrul lor, cuprinse ntre dou valori
ntregi citite de la tastatur.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_35
{
class Program
{
static void Main(string[] args)
{
int a, b, x, k = 0; // k va determina cate numere prime sunt in
interval
do
{
Console.Write("Dati prima valoare : ");
a = Convert.ToInt32(Console.ReadLine());
} while (a <= 0);
do
{
Console.Write("Dati a doua valoare : ");
b = Convert.ToInt32(Console.ReadLine());
} while (b <= a);
42
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_36
{
class Program
{
static void Main(string[] args)
{
double rc, ic;
double x, y, z;
int n;
for (ic = 1.4; ic >= -1.4; ic -= 0.05)
{
for (rc = -0.7; rc <= 1.80; rc += 0.05)
{
43
n = 0;
x = ic * ic + rc * rc;
y = 2 * ic - 4 * rc;
z = x * x + y * y;
while (n <= 40 && z < 5)
{
x = ic * ic + rc * rc - rc;
y = 2 * ic - 4 * rc;
z = x * x - y * y;
n++;
}
switch (n % 4)
{
case 0: Console.Write("*");
case 1: Console.Write("$");
case 2: Console.Write("o");
case 3: Console.Write("@");
}
}
Console.WriteLine();
}
}
44
break;
break;
break;
break;
45
46
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;
}
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();
}
}
}
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");
}
}
}
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();
}
}
}
}
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
Prin aceast declaraie nu se aloc i spaiu pentru memorare. Pentru aceasta, tabloul
trebuie instaniat:
nume = new Tip[NumarElemente];
sau
int[] v = {1,2,3);
//afisarea vectorului v
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
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}
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
iar instanierea:
nume = new Tip[Linii,Coloane];
Accesul:
nume[indice1,indice2]
58
sau
int[,] mat = {{1,2,3},{4,5,6},{7,8,9}};
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 }
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:
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
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();
}
}
}
Efect
apostrof
ghilimele
backslash
null
alarm
backspace
form feed pagin nou
new line linie nou
carriage return nceput de rnd
64
\t
\u
\v
\x
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_50
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul C#";
string b = "Invat " + "limbajul ";
b += "C#";
Console.WriteLine("a='{0}'", a);
Console.WriteLine("b='{0}'", b);
Console.WriteLine("a == b {0}", a == b);
Console.WriteLine("(object)a == b {0}", (object)a == b);
}
}
}
65
metode de comparare:
-
Compare
CompareOrdinal
CompareTo
EndsWith
StartsWith
IndexOf
LastIndexOf
metode care permit modificarea irului curent prin obinerea unui nou ir:
-
Concat
CopyTo
Insert
Join
PadLeft
PadRight
Remove
Replace
Split
Substring
ToLower
ToUpper
Trim
TrimEnd
TrimStart
Proprietatea Length am folosit-o pe parcursul acestei lucrri i, dup cum tim returneaz un
ntreg care reprezint lungimea (numrul de caractere) irului.
66
Tabelul de mai jos prezint cteva dintre funciile (metodele) clasei String
Funcia (metod a clasei Strig)
string Concat(string u, string v)
int IndexOf(char c)
int IndexOf(string s)
string Insert(int a, string s)
string Remove(int a, int b)
string Replace(string u, string v)
string Split(char[] c)
string Substring(int index)
string Substring(int a, int b)
string ToLower()
string ToUpper()
string Trim()
string TrimEnd()
string TrimStart()
Descrierea
returneaz un nou ir obinut prin concatenarea
irurilor u i v
returneaz indicele primei apariii a caracterului
c n ir
returneaz indicele primei apariii a subirului s
returneaz un nou ir obinut din cel iniial prin
inserarea n irul iniial, ncepnd cu poziia a,
a irului s
returneaz un nou ir obinut din cel iniial prin
eliminarea, ncepnd cu poziia a, pe o lungime
de b caractere
returneaz un nou ir obinut din cel iniial prin
prin nlocuirea subirului u cu irul v
mparte un ir n funcie de delimitatorii c
returneaz un nou ir care este un subir al
irului ini ial ncepnd cu indicele index
returneaz un nou ir care este un subir al
irului iniial, ncepnd de pe poziia a, pe
lungimea b caractere
returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la minuscule
returneaz un nou ir obinut din cel iniial prin
convertirea tuturor caracterelor la majuscule
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la nceputul i
sfritul irului ini ial
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la sfritul irului
ini ial
returneaz un nou ir obinut din cel iniial prin
tergerea spaiilor goale de la nceputul irului
ini ial
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_51
{
class Program
{
static void Main(string[] args)
{
string a = "Invat limbajul ";
string b = "C#";
string c;
Console.WriteLine("a = '{0}'", a);
Console.WriteLine("b = '{0}'", b);
67
c = string.Concat(a, b);
Console.WriteLine("string.Concat(a, b) = \"{0}\"", c);
Console.WriteLine("a.IndexOf(\"v\") = {0}",
Convert.ToString(a.IndexOf("v")));
Console.WriteLine("a.IndexOf(\"mba\") = {0}",
Convert.ToString(a.IndexOf("mba")));
Console.WriteLine("a.Insert(6, \"de zor \") = {0}", a.Insert(6,
"de zor "));
Console.WriteLine("a.Remove(5, 7) = {0}", a.Remove(5, 7));
Console.WriteLine("a.Replace(\"limbajul \", \"la informatica.\")
= {0}", a.Replace("limbajul ", "la informatica."));
Console.WriteLine("a.Substring(6) = {0}", a.Substring(6));
Console.WriteLine("a.Substring(10, 3) = {0}", a.Substring(10,
3));
Console.WriteLine("a.ToLower() = {0}", a.ToLower());
Console.WriteLine("a.ToUpper() = {0}", a.ToUpper());
string d = "
Ana are mere.
";
Console.WriteLine("d = {0}", d);
Console.WriteLine("d.Trim() = {0}", d.Trim());
Console.WriteLine("d.TrimStart() = {0}", d.TrimStart());
}
}
}
68
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
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
Exemplul 56:
using
using
using
using
System;
System.Collections.Generic;
System.Text;
System.IO;
namespace Exemplul_56
{
class Program
{
static void Main(string[] args)
{
string[] a = { "primul", "fisier", "creat", "de mine", };
//deschiderea unui fisier si atasarea lui la un flux
StreamWriter outputFile = File.CreateText("C:\\C#\\fisier1.txt");
72
foreach (string b in a)
{
outputFile.WriteLine(b);//scrierea textului in fisier
}
//inchiderea fisierului
outputFile.Close();
//deschidem din nou fisierul de data aceasta pentru a citi din el
StreamReader inputFile = File.OpenText("C:\\C#\\fisier1.txt");
//definim o variabila string care va parcurge fisierul pana la
final
}
}
string x;
while ((x = inputFile.ReadLine()) != null)
{
System.Console.WriteLine(x);
}
//inchidem fisierul
inputFile.Close();
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
modul_1
modul_2
(date+date1)
subprog_1
subprog_2
subprog_3
(date+date2)
subprog_1
subprog_2
Se observ c modulele sunt centrate pe proceduri, acestea gestionnd i setul de date pe care
le prelucreaz (date+date1 din figur). Dac, de exemplu, dorim s avem mai multe seturi diferite
de date, toate nzestrate comportamental cu procedurile din modulul modul_1, aceast arhitectur
de aplicaie nu este avantajoas.
Programarea orientat obiect POO (programe cu noi tipuri ce integreaz att datele, ct
i metodele asociate crerii, prelucrrii i distrugerii acestor date); se obin avantaje prin
75
obiect4
date1
met1
date4
met4
obiect3
date3
met3
obiect2
date2
met2
via, au diverse proprieti, sunt capabile de aciuni specifice i care interacioneaz n cadrul
programului); intervin tehnici noi privind instanierea, derivarea i polimorfismul tipurilor obiectuale.
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:
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),
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:
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.
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
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#.
unde:
public sunt modificatori de acces.
class cuvnt rezervat pentru noiunea de clas
Copil numele clasei
Copil
{ } corpul clasei
Dac considerm clasa Copil ca i clas de baz,
Fetita
Baiat
unde:
modificatorul sealed a fost folosit pentru a desemna faptul c nu se mai pot ob ine clase derivate
din clasa Baiat
I.4.2. Constructori
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
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;
public Copil ( )
{
nume = Console.ReadLine( );
}
}
class Fetita: Copil
{ }
...
Fetita f = new Fetita ( );
Copil c = new Copil ( );
83
}
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
//constructor cu parametru
Exemplul 62:
85
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
Clase
unde:
atribut este opional, reprezentnd informaii declarative cu privire la entitatea definit
modificatorAcces - este opional, iar n cazul n care lipsete se consider public
modificatorAcces
public
Explicaii
acces nelimitat, clasa este vizibil peste tot
internal
protected
private
protected internal
new
sealed
abstract
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
}
}
}
date
funcii
Explicaii
Membrul este accesibil de oriunde
internal
89
protected
private
protected internal
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
unde tip poate fi: bool, decimal, sbyte, byte, short, ushort, int, uint, long,
ulong, char, float, double, enum, string
90
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:
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
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
}
Cmpuri volatile
Cmpurile volatile se declar cu ajutorul cuvntului volatile, care poate fi ataat doar
urmtoarelor tipuri:
un tip enumerare care are tipul: byte, sbyte, short, ushort, int, uint
un tip referin
Iniializarea cmpurilor
Valorile implicite pe care le iau cmpurile la declararea lor sunt:
tip
numeric
bool
char
enum
referin
valoare
0
false
\0
0
null
I.5.1.(2) Funcii
Funciile pot fi:
Constructori
Destructori
Metode
Proprieti
Evenimente
Indexatori
Operatori
I.5.1.(3)
Constructori
Definiie: Constructorii sunt funcii care folosesc la iniializarea unei instane a clasei.
Constructorii au acelai nume cu al clasei. Constructorul poate avea un modificator de acces i nu
returneaz nimic. Sintaxa este:
modificatorAcces numeConstructor([parametri])[:initializator]
[{
corp_constructor
}]
93
unde:
initializator permite invocarea unui constructor anume, nainte de executarea
instruciunilor care formeaz corpul constructorului curent. Iniializatorul poate lua dou forme:
base([parametri]) sau this([parametri]). Dac nu se precizeaz niciun iniializator,
implicit se va asocia base( ).
n cazul n care nu definim nici un constructor, C# va crea unul implicit avnd corpul vid.
Exemplul 69:
class Elev
{
public Elev()
{
}
}
//constructor
O clas poate conine mai muli constructori, difereniai dup numrul i tipul de parametri.
Exemplul 70:
class Elev
{
public string nume;
public Elev()
//constructor
{
nume = "";
}
public Elev(string Nume) //constructor
{
nume = Nume;
}
}
Apelul unui constructor se face automat la instanierea clasei prin operatorul new.
Exemplul 71:
class Exemplu_71
{
Elev elev = new Elev();
}
94
using System;
namespace Complex
{
class Complex
{
private int re;
private int im;
//constructor cu doi parametri
public Complex(int i, int j)
{
re = i;
im = j;
}
public void Afis()
{
Console.WriteLine(re + "+" + im + "i");
}
}
class Program
{
static void Main(string[] args)
{
Complex c = new Complex(1, 2);
c.Afis();
Console.ReadLine();
}
}
}
I.5.1.(4) Destructori
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
parametri - lista de parametri formali este o succesiune de declarri desprite prin virgule,
declararea unui parametru avnd sintaxa:
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
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]
[nume_clas].[nume_metoda]
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
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:
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
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,
102
internal,
private,
unde:
listaParametrilorFormali trebuie s conin cel puin un parametru, parametru care nu trebuie s
fie de tipul ref sau out.
indexatorii pot folosi indici nenumerici, pe cnd un vector trebuie s aib indicii de tip ntreg
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
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
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_77
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void Afis()
{
Console.WriteLine("{0} {1}i", x, y);
}
105
class Program
{
public static void Main()
{
Complex c1 = new Complex(10, 13);
c1.Afis();
Complex c2 = new Complex();
c2.Afis();
c2 = -c1;
c2.Afis();
Console.ReadLine();
}
}
}
Operatori binari
Suprancrcarea operatorilor binari are urmtoarea sintax:
tip operator operatorBinarSuprancrcabil (tip identificator,
tip identificator) corp
Operatorii binari suprancrcabili sunt: + - * / & | ^ << >> == != > < >= <=
Reguli pentru suprancrcarea operatorilor binari:
1. Cel puin unul din cei doi parametri trebuie s fie de tipul clasei n care respectivul operator
a fost declarat
2. Operatorii de shift-are trebuie s aib primul parametru de tipul clasei n care se declar,
iar al doilea parametru de tip int
3. Un operator binar poate returna orice tip
4. Urmtorii operatori trebuie s se declare n pereche:
a. operatorii == i !=
b. operatorii > i <
c. operatorii >= i <=
Exemplul 78:
106
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace ExempluOperatori
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void Afis()
{
Console.WriteLine("{0} {1}", x, y);
}
Operatori de conversie
107
implicii se efectueaz de la un tip mai mic la un tip mai mare i reuesc ntotdeauna,
nepierzndu-se date
Un operator de acest tip va face conversia de la tipul sursa (S) (tipul parametrului din antet)
n tipul destinaie (D) (tipul returnat).
O clas poate s declare un operator de conversie de la un tip S la un tip D dac:
1. S i D au tipuri diferite
2. S sau D este clasa n care se face definirea
3. S i D nu sunt object sau tip interfa
4. S i D nu sunt baze una pentru cealalt
Exemplu 79: conversii dintr-un tip de baz ntr-o clas i un tip clas ntr-un tip de baz folosind
conversia operator:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_79
{
class MyDigit
{
private int x;
public MyDigit()
{
}
public MyDigit(int i)
{
x = i;
}
public void ShowDigit()
{
Console.WriteLine("{0}", x);
}
public static implicit operator int(MyDigit md)
{
return md.x;
}
public static explicit operator MyDigit(int val)
{
return new MyDigit(val);
}
}
108
class Program
{
public static void Main(string[] args)
{
MyDigit md1 = new MyDigit(10);
int x = md1;
//Implicit
Console.WriteLine(x);
int y = 25;
MyDigit md2 = (MyDigit)y; //Explicit
md2.ShowDigit();
Console.ReadLine();
}
}
Exemplul 80: Conversia dintr-un tip clas n altul folosind conversia operator:
109
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace OperatoriImplicitiExpliciti
{
class Clasa1
{
public int x;
public Clasa1(int a)
{
x = a;
}
public void Afis1()
{
Console.WriteLine(x);
}
public static explicit operator Clasa2(Clasa1 mc1)
{
Clasa2 mc2 = new Clasa2(mc1.x * 10, mc1.x * 20);
return mc2;
}
}
class Clasa2
{
public float x, y;
public Clasa2(float a, float b)
{
x = a;
y = b;
}
public void Afis2()
{
Console.WriteLine(x);
Console.WriteLine(y);
}
}
class Program
{
public static void Main(string[] args)
{
Clasa1 mc1 = new Clasa1(100);
mc1.Afis1();
Clasa2 mc2 = (Clasa2)mc1;
mc2.Afis2();
Console.ReadLine();
}
}
}
110
I.6.
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();
111
interface IGeneric1<T>
{ }
class ClassGeneric1<UnTip, Altul>
{ }
class ClassInt1 : ClassGeneric1<int, int>
{ }
class ClassInt2<T> : ClassGeneric1<int, T>
{ }
class ClassInt3<T, U> : ClassGeneric1<int, U>
{ }
Exemplul 84:
elemente. Pentru a simplifica problema, vom considera c stiva nu poate conine dect un anumit
numr de elemente, ceea ce ne va permite s utilizm tablouri n C#.
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_84
{
class Stiva
{
private object[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new object[MAX_SIZE]; }
public Object Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}
112
class Program
{
static void Main(string[] args)
{
Stiva stiva = new Stiva();
stiva.Push(1234);
int numar = (int)stiva.Pop();
}
}
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
113
Exemplul 85:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_85
{
class Stiva<T>
{
private T[] m_ItemsArray;
private int m_Index = 0;
public const int MAX_SIZE = 100;
public Stiva() { m_ItemsArray = new T[MAX_SIZE]; }
public T Pop()
{
if (m_Index == 0)
throw new InvalidOperationException("Nu putem extrage un
element dintr-o stiva vida.");
return m_ItemsArray[--m_Index];
}
public void Push(Object item)
{
if (m_Index == MAX_SIZE)
throw new StackOverflowException("Nu se poate adauga un
elemet: stiva este plina.");
m_ItemsArray[m_Index++] = item;
}
}
class Program
{
static void Main(string[] args)
{
Stiva<int> stiva = new Stiva<T>();
stiva.Push(1234);
int numar = stiva.Pop(); //nu mai este necesar cast
Stiva<string> sstiva = new Stiva<string>();
sstiva.Push("4321");
string sNumar = sstiva.Pop();
}
}
I.7.
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.
Clasa derivat motenete toate elementele clasei de baz i-i adaug altele proprii.
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
Violonist
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.
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);
}
}
class ClasaDeBaza
{
protected string var;
public ClasaDeBaza(string var)
{
this.var = var;
}
}
//constructor
I.7.3.
Metode
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
unei averi, atunci o clas VENIT nu este posibil, deoarece ea ar moteni de la toate clasele
evideniate, iar motenirea multipl nu este admis n C#.
AVERE
Proprietate
Imobiliara
Bani
Bun
Teren
Depunere
Credit_primit
Investiie
B_inchiriat
Actiune
Productiv
Mobilier
Cot
Neproductiv
Altul
Credit_acordat
VENIT
Imobil
De_folosin
I_inchiriat
Pentru metodele din cadrul unei interfee nu se d nici o implementare, ci sunt pur i simplu
specificate, implementarea lor fiind furnizat de unele dintre clasele aplicaiei. Acele clase care
ader la o interfa spunem c implementeaz interfaa respectiv. Nu exist instaniere n
cazul interfeelor, dar se admit derivri, inclusiv moteniri multiple.
n exemplul nostru, se poate defini o interfa VENIT care s conin antetul unei metode
calc (s zicem) pentru calculul venitului obinut, fiecare dintre clasele care implementeaz interfaa
VENIT fiind obligat s furnizeze o implementare (dup o formul de calcul specific) pentru
metoda calc din interfa. Orice clas care dorete s adere la interfa trebuie s implementeze
toate metodele din interfa. Toate clasele care motenesc dintr-o clas care implementeaz o
interfa motenesc, evident, metodele respective, dar le pot i redefini (de exemplu, clasa
Credit_acordat redefinete metoda calc din clasa Investiie, deoarece formula de calcul
implementat acolo nu i se potrivete i ei. Dac n sens polimorfic spunem c Investiie este i
de tip Bani i de tip Avere, tot aa putem spune c o clas care implementeaz interfaa VENIT
i clasele derivate din ea sunt i de tip VENIT).
De exemplu, dac presupunem c toate clasele subliniate implementeaz interfaa
VENIT, atunci pentru o avere cu aciuni la dou firme, un imobil nchiriat i o depunere la banc,
putem determina venitul total:
Exemplul 91:
120
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:
mpriri la zero
etc.
SystemException
OutOfMemoryException
IOException
NullReferenceException
AplicationException
Ierarhia excepiilor
121
Explicaii
sunt constructori
C# definete cteva excepii standard derivate din System.Exception. Acestea sunt generate
cnd se produc erori la execu ia programului. Dintre acestea amintim:
Excepia
Explicaii
Incompatibilitate ntre tipul valorii
memorate i tipul tabloului
ncercare de mprire la zero
ArrayTypeMismatchException
DivideByZeroException
IndexOutOfRangeException
InvalidCastException
OutOfMemoryException
OverflowException
StackOverflowException
122
I.8.1.
scrierea codului, programatorul va separa acele instruciuni care sunt sigure (adic nu pot fi
generatoare de excepii), de cele care sunt susceptibile s conduc la erori. Partea de program
care poate genera excepii o vom plasa ntr-un bloc try, iar partea corespunztoare tratrii
excepiei, ntr-un bloc catch.
n cazul n care blocul try genereaz o excepie, Runtime ntrerupe execuia i caut un bloc
catch apropiat care, n funcie de tipul su s poat trata respectiva eroare. n cazul n care este
gsit respectivul bloc catch programul continu cu instruciunile din corpul catch. n cazul n care
nu se gsete nici un catch corespunztor, execuia programului este ntrerupt.
Avnd n vedere c ntr-un corp try pot s apar excepii diferite, n program pot exista mai
multe blocuri corespunztoare catch.
Exemplul 91:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exceptii1
{
class Program
{
static void Main(string[] args)
{
try
{
Console.Write("Introduceti un numar ");
int i = int.Parse(Console.ReadLine());
Console.Write("Introduceti inca un numar ");
int j = int.Parse(Console.ReadLine());
int x = i / j;
}
catch (OverflowException e)
{
Console.WriteLine("Numarul nu este intreg");
//Console.WriteLine(e);
}
123
//(1)
//(2)
/*
catch (DivideByZeroException e)
{
//Console.WriteLine(e);
//(3)
Console.WriteLine("Exceptia DivideByZero");
//(4)
}*/
Console.WriteLine("Programul ruleaza in continuare");//(5)
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.
124
Exemplul 92:
class Program
{
static void Main(string[] args)
{
try
//(1)
{
//(2)
Console.Write("Introduceti o cifra ");
int i = int.Parse(Console.ReadLine());
if (i < 0 || i > 9)
{
string exceptie = i + " nu este o cifra";
//(0)
throw new ArgumentOutOfRangeException(exceptie);
}
}
//(3)
catch (ArgumentOutOfRangeException)
//(4)
{
//(5)
Console.WriteLine("Nu este cifra");
//(6)
}
//(7)
Console.WriteLine("Programul ruleaza in continuare");
}
}
}
Dac 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
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.9.
Polimorfism
I.9.1.
Introducere
polimorfism parametric
polimorfism ad-hoc
polimorfism de motenire
I.9.2.
Polimorfismul parametric
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_93
{
class Program
{
static void F(params int[] arg)
{
Console.WriteLine("Apelul functiei F cu {0} parametri:",
arg.Length);
for (int i = 0; i < arg.Length; i++)
{
Console.WriteLine("arg[{0}] = {1}", i, arg[i]);
}
Console.WriteLine("");
}
static void Main(string[] args)
{
F();
F(2);
F(4, 6);
F(new int[] { 1, 2, 3 });
}
}
}
127
I.9.3.
Polimorfismul ad-hoc
Acest tip de polimorfism se mai numete i suprancrcarea metodelor. Prin acest mecanism
se pot defini n cadrul unei clase mai multe metode, toate avnd acelai nume, dar cu tipul i
numrul de parametri diferii. La compilare, n funcie de parametri folosii la apel, se va apela o
funcie sau alta.
Exemplul 94:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace PolimorfismAdHoc
{
class Program
{
static void F()
{
Console.WriteLine("Functia F fara parametri\n");
}
static void F(int a, int b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
int\n");
}
static void F(int a, double b)
{
Console.WriteLine("Functia F cu doi parametri: int si respectiv
float\n");
}
static void Main(string[] args)
{
F();
F(2, 3);
F(4, 6.3);
}
}
}
128
I.9.4.
Polimorfismul de motenire
n cazul acestui tip de motenire vom discuta ntr-o ierarhie de clase. n acest caz ne
punem problema apelrii metodelor, avnd aceeai list de parametri formali, metode ce
fac parte din clase diferite.
Exemplul 95:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_95
{
class Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis();
//(1)
obiect2.Afis();
//(2)
}
}
}
129
S discutm despre prima linie afiat (cea de-a doua este evident). Apelul lui Afis() se
rezolv n momentul compilrii pe baza tipului declarat al obiectelor. Deci linia (1) din program va
duce la apelul lui Afis() din clasa Baza, chiar dac obiect1 a fost instaniat pe baza unui obiect
din clasa Derivata.
I.9.5.
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace Exemplul_96
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public override void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis();
//(1)
obiect2.Afis();
//(2)
}
}
}
130
I.9.6.
Modificatorul new
n cazul n care se dorete ca o metod dintr-o clas derivat s aib aceeai semntur cu
o metod dintr-o clas de baz, dar s nu fie considerat o suprascriere a ei, vom folosi
modificatorul new.
Exemplul 97:
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace PolimorfismDeMostenire
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din clasa de baza\n");
}
}
class Derivata : Baza
{
public new void Afis()
// !!! new
{
Console.WriteLine("Apelul functiei Afis din clasa derivata\n");
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = obiect2;
obiect1.Afis();
//(1)
obiect2.Afis();
//(2)
}
}
}
131
I.9.7.
Metoda sealed
O metod avnd tipul override poate fi declarat sealed. n acest fel ea nu mai poate fi
suprascris ntr-o clas derivat
Exemplul 98:
using System;
using System.Collections.Generic;
using System.Text;
namespace Exemplul_98
{
class Baza
{
public virtual void Afis()
{
Console.WriteLine("Apelul functiei Afis din
}
}
class Derivata : Baza
{
sealed override public void Afis()
{
Console.WriteLine("Apelul functiei Afis din
}
}
class Derivata2 : Derivata
{
override public void Afis()
//!!! EROARE
{
Console.WriteLine("Apelul functiei Afis din
}
}
class Program
{
static void Main(string[] args)
{
Derivata obiect2 = new Derivata();
Baza obiect1 = new Derivata();
Derivata2 obiect3 = new Derivata2();
obiect1.Afis();
obiect2.Afis();
obiect3.Afis();
}
}
}
132
clasa de baza\n");
clasa derivata\n");
!!!
clasa Derivata2\n");
//(1)
//(2)
Va genera eroare, deoarece modificatorul sealed al metodei Afis(), din clasa Derivata, va
mpiedic suprascrierea acestei metode n clasa Derivata2.
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.
133
II.2.
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());
II.3.
n cele ce urmeaz pentru explicaiile care vor avea loc vom considera o aplicaie Windows
numit Test:
136
Fereastra Toolbox
Fereastra Properties
Fereastra pentru
afiarearea Listei de
erori
Bara de unelte
Fereastra Solution
Explorer
Bara de meniuri
Toate ferestrele, au n partea dreapt o piunez, care, dac este n poziie vertical
fixez fereastra deschis. n caz contrar
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
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
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
140
Solution
Explorer,
din
partea
se
va
deschide,
nc
ferestr
lucru
putem
spune
despre
Fereastra Properties
Aminteam mai sus c n Toolbox exist toate tipurile de controale care i sunt necesare
unui programator pentru a realiza o aplicaie.
Cele
mai
multe
controale
System.Windows.Forms.Control.
sunt
Datorit
obiecte
acestui
141
de
fapt
clase
multe
derivate
dintre
din
clasa
proprietile
evenimentele diverselor controale vor fi identice. Vom vedea, n aplicaiile care urmeaz, c exit
clase care definesc controale i care pot fi clase de baz pentru alte controale.
Fereastra Properties, din interfaa mediului de programare, vom observa c va conine
att proprietile ct i evenimentele ataate controalelor.
motenite sau supranscrise din clasa de baz Control. Tabelul de mai jos prezint proprietile
comune controalelor, proprieti furnizate de ctre clasa Control:
Proprietatea
Anchor
BackColor
Bottom
Dock
Enabled
ForeColor
Height
Left
Name
Parent
Right
TabIndex
TabStop
Tag
Top
Visible
Width
Descrierea proprietii
se refer la posibilitatea de a ancora controlul fa de o margine (sau
toate)
permite stabilirea culorii de fundal a controlului
permite stabilirea distanei dintre marginea de sus a ferestrei i control
ataeaz controlul la una dintre marginile ferestrei
permite controlului s recepioneze evenimente de la utilizator
permite stabilirea culorii textului
permite definirea nlimii controlului
permite stabilirea distanei dintre marginea din stnga a ferestrei i
marginea stnga a controlului
permite denumirea controlului pentru a-l putea mai uor vizualiza i
manipula n codul surs
printele controlului
permite stabilirea distanei dintre marginea din dreapta a ferestrei i
marginea din dreapta a controlului
prin numrul de ordine care i se ataeaz se stabilete ordinea activrii
controlului la apsarea tastei TAB
permite sau nu ca respectivul control s fie activat prin apsarea tastei
TAB
se refer la un ir de caractere pe care controlul l poate stoca n interiorul
su
permite stabilirea distanei dintre marginea de sus a ferestrei i marginea
de sus a controlului
stabilete dac respectivul control, care exit n fereastr, este (TRUE)
sau nu vizibil
stabilete limea controlului
reaciona, printr-o secven de cod sau alta. Tot clasa Control amintit mai sus, implementeaz
i o serie de evenimente la care controalele vor reaciona:
Evenimentul
Clic
DoubleClic
DragDrop
Descrierea evenimentului
se genereaz cnd se d clic asupra unui control
se genereaz cnd se d dublu clic asupra unui control. Excepie fcnd
Button asupra cruia nu se va putea face dublu clic, deoarece controlul
acioneaz la primul clic
se genereazla finalizarea lui drag and drop
142
Evenimentul
DragEnter
Descrierea evenimentului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge n
interiorul controlului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge s
prseasc controlului
se genereaz atunci cnd obiectul, printr-un drag and drop, ajunge
deasupra controlului
se genereaz atunci cnd o tast este apsat n timp ce controlul este
activ. Se va furniza codul ASCII al tastei apsate. Se genereaz nainte
de evenimentele KeyPress i KeyUp
se genereaz atunci cnd o tast este apsat n timp ce controlul este
activ. Se va furniza codul de scanare al tastei apsate. Se genereaz
dup KeyDown i nainte de KeyUp
se genereaz cnd o tast este eliberat n timp ce controlul este activ.
Se genereaz dup KeyDown i KeyPress
se genereaz cnd controlul devine activ (se mai spune: cnd controlul
primete input focusul)
se genereaz cnd controlul devine inactiv (se mai spune: cnd controlul
pierde input focusul)
se genereaz cnd cursorul mouse-ului este deasupra controlului i se
apas un buton al mouse-ului
se genereaz cnd trecem cu mouse-ul deasupra controlului
se geereaz cnd mouse-ul este deasupra controlului i eliberm un
buton al mouse-ului
se genereaz la desenarea controlului
se genereaz cnd un control este pe cale s devin activ. Se genereaz
dup terminarea evenimentului Validating, indicnd faptul c validarea
controlului este complet
se genereaz cnd un control este pe cale s devin activ
DragLeave
DragOver
KeyDown
KeyPress
KeyUp
GotFocus
LostFocus
MouseDown
MouseMove
MouseUp
Paint
Validated
Validating
II.4.
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
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.).
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.
Vizibilitatea unui formular poate fi setat folosind metodele Hide sau Show. Pentru a
ascunde un formular putem folosi :
this.Hide();
144
StartPosition determin poziia ferestrei atunci cnd aceasta apare prima dat. Poziia poate fi
setat Manual, sau poate fi
Windows-ul
va
stabili
dimensiunea
iniial
locaia
pentru
formular
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).
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.
ControlBox precizeaz dac fereastra conine sau nu un icon, butonul de nchidere al ferestrei
i meniul System (Restore,Move,Size,Maximize,Minimize,Close).
145
ShowInTaskbar precizeaz dac fereastra apare in TaskBar atunci cnd formularul este
minimizat.
SizeGripStyle specific tipul pentru Size Grip (Auto, Show, Hide). Size grip
(n colul din
TopMost precizeaz dac fereastra este afisat n faa tuturor celorlalte ferestre.
selectarea grupului
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.
II.4.2.
Controale
Unitatea de baz a unei interfee Windows o reprezint un control. Acesta poate fi gzduit
de un container ce poate fi un formular sau un alt control.
Un control este o instan a unei clase derivate din System.Windows.Forms i este
reponsabil cu desenarea unei pri din container. Visual Studio .NET vine cu o serie de controale
standard, disponibile n Toolbox. Aceste controale pot fi grupate astfel:
146
Controale form. Controlul form este un container. Scopul su este de a gzdui alte controale.
Folosind proprietile, metodele i evenimentele unui formular, putem personaliza programul
nostru.
n tabelul de mai jos vei gsi o list cu controalele cel mai des folosite i cu descrierea lor.
Exemple de folosire a acestor controale vor urma dup explicarea proprietilor comune al
controalelor i formularelor.
Funcia
controlului
buton
Numele
controlului
Button
calendar
MonthCalendar
caset de
validare
etichet
CheckBox
caset cu
list
imagine
ListBox
pointer
Pointer
buton radio
RadioButton
Label
PictureBox
II.5.
Descriere
Sunt folosite pentru a executa o secven de instruciuni n
momentul activrii lor de ctre utilizator
Afieaz implicit un mic calendar al lunii curente. Acesta
poate fi derulat i nainte i napoi la celelalte luni
calendaristice.
Ofer utilizatorului opiunile : da/nu sau include/exclude
Sunt folosite pentru afiarea etichetelor de text, i a pentru a
eticheta controalele.
Afieaz o list de articole din care utilizatorul poate alege.
Este folosit pentru adugarea imaginilor sau a altor resurse
de tip bitmap.
Este utilizat pentru selectarea, mutarea sau redimensionarea
unui control.
Este folosit pentru ca utilizatorul s selecteze un singur
element dint-un grup de selecii.
Este utilizat pentru afiarea textului generat de o aplicaie
sau pentru a primi datele introduse de la tastatur de ctre
utilizator.
Aplicaii
II.5.1.
Numere pare
Acest exemplu afieaz numerele pare din intervalul [0,n) unde n este o variabil global a
crei valoare este introdus de la tastatur. Se deschide o aplicaie Windows Forms pe care o vei
denumi Numere pare. Din fereastra Properties modificai numele formularului. Stabilii dimensiunea
formularului i culoarea de fond alegnd una dintre cele predefinite din opiunea BackColor.
Cu ajutorul metodei Drag and drop plasai pe formular un buton pe care vei introduce textul
START, dou controale TextBox, dou controale label pe care vei introduce textele din exemplul
de mai jos
147
Executai dublu clic pe butonul START i editai codul surs conform exemplului de mai jos:
n acest moment aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.
148
II.5.2.
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 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 TabIndex seteaz sau returneaz poziia controlului n cadrul aranjrii taburilor.
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.
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:
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
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:
Vei obine la rularea aplicaiei afiarea uneia din cele dou imagini, n funcie de butonul apsat.
sau
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.
152
Exemplul 6:
Este un exemplu de utilizare a
Propietatea Checked
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
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.
n aceeai fereastr de cod scriem funcia recursiv patrat care va genera fractalul.
if (n > 1)
{
patrat(n - 1, x - l4, y - l4, l2);
patrat(n - 1, x - l4, y + l3, l2);
patrat(n - 1, x + l3, y - l4, l2);
patrat(n - 1, x + l3, y + l3, l2);
}
Graphics graph = this.CreateGraphics();
Pen penc;
if (n % 2 == 0) penc = new Pen(Color.Red);
else penc = new Pen(Color.BlueViolet);
Point[] p = new Point[4];
p[0].X = x; p[0].Y = y;
p[1].X = x; p[1].Y = y + l;
p[2].X = x + l; p[2].Y = y + l;
p[3].X = x + l; p[3].Y = y;
graph.DrawPolygon(penc, p);
}
155
Se execut acum dublu clic pe obiectul timer de pe formular pentru a completa funcia
timer1_Tick cu apelul funciei recursive patrat.
n acest moment aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.
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.
astfel:
this.button1.MouseEnter += new System.EventHandler(this.button1_MouseEnter);
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
158
astfel:
this.button1.MouseLeave += new System.EventHandler(this.button1_MouseLeave);
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:
n acest moment aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.
159
160
161
Executai dublu clic pe controlul timer i completai funcia timer1_Tick conform modelului
de mai jos:
162
n acest moment aplicaia este gata. Din meniul File alegei opiunea Save All i rulai
aplicaia.
Metoda Dispose()
Exemplul 13:
163
Click
asociat
(listBox1.Items.Clear();)
butonului
Selectie
golete
mai
nti
listBox-ul
164
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:
Columns (utilizat doar n modul Details, pentru a defini coloanele de afiat), Items (elementele
de afiat).
Exemplul acesta afi eaz ntr-un ListView o list de elevi. Clasa Elev con ine
i o metod
static ce returneaz o list de elevi (ne putem imagina c lista respectiv e citit din baza de
date), este aceasta:
class Elev
{
public string Nume { get; set; }
public string Prenume { get; set; }
public int Nota { get; set; }
public static List<Elev> CitesteElevi()
{
List<Elev> elevi = new List<Elev>();
elevi.Add(new Elev() { Nume = "Nume 1",
Nota = 9 });
elevi.Add(new Elev() { Nume = "Nume 2",
Nota = 10 });
elevi.Add(new Elev() { Nume = "Nume 3",
Nota = 8 });
elevi.Add(new Elev() { Nume = "Nume 4",
Nota = 9 });
return elevi;
}
}
165
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();
}
167
Evenimentul DateSelected
Exemplul 17: MonthCalendar
MonthCalendar afieaz un calendar prin care se poate selecta o dat (zi, luna, an) n mod
grafic. Proprietile mai importante sunt: MinDate, MaxDate, TodayDate ce reprezint data
minim/maxim selectabil i data curent (care apare afiat difereniat sau nu n funcie de
valorile proprietilor ShowToday,ShowTodayCircle.
Exist 2 evenimente pe care controlul le expune: DateSelected i DateChanged. n rutinele
de
tratare
acestor
evenimente,
programatorul
are
acces
la
un
obiect
de
tipul
168
textului introdus n caset. Toolbar-ul se poate muta fr a depi spaiul ferestrei. Schimbarea
fontului se realizeaz cu ajutorul
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
Metoda ShowDialog()
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.
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);
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;
172
care permite
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.
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.
174
II.5.5.(3) ErrorProvider
O manier simpl de a semnala erori de validare este aceea de a seta un mesaj de eroare
pentru fiecare control .
II.5.6.
MessageBox
175
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
177
II.5.7.
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
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
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
182
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
}
Mai includem n sursa noastr i:
183
using System.Runtime.InteropServices;
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
System.Runtime.InteropServices;
namespace Interfata3
{
public partial class Form1 : Form
{
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr Handle, int Msg,
int Param1, int Param2);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void pictureBox1_MouseDown(object sender,
MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
}
}
}
}
184
185
II.5.8.
WebBrowser pe care l aliniem dup laturile din stnga, dreapta i jos a ferestrei.
Rulm programul i n TextBox vom scrie o adres web. Surpriz plcut, navigatorul nostru
funcioneaz!
186
187
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
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
Anchor
textBox
button
Top, Right
webBrowser
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
Valoare
aplCeas
Explicaie
Enabled
Interval
True
1.000
Proprietate
(Name)
AutoSize
BorderStyle
FontSize
Location
Valoare
labelCeas
False
Fixed3D
16,25, Bold
82;112
192
Text
Size
TextAlign
129;42
MiddleCenter
Compilm
obinem
ntr-o
fereastr
193
II.6.
II.6.1.
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.
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.
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
II.6.3.
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.
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:
pentru a insera rnduri multiple ntr-un tabel se folosete o instruciune SELECT intern
va incrementa aceast
nregistrri, nregistrare care va primi pe coloana NUME valoarea POPESCU. Pentru a vizualiza
modificarea folosii instruciunea SELECT.
199
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,,>
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
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.
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);
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
Dup cum observai se pot vizualiza cmpurile definite n tabela Flori. Pentru a popula
aceasta tabel trebuie s o deschidei cu Open.
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.
204
II.7.
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.
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
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
II.8.
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
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.
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:
Sau implicit :
211
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
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.
SqlCommand()
SqlCommand cmd = new SqlCommand();
215
Exemplul 6: Am construit o nou tabel tot n baza de date salarii numit telefoane. Coninutul
ei este prezentat mai jos.
Metoda
ExecuteReader()
mai
are
un
argument
opional
de
tip
enumerare,
Exemplul 7: cele dou surse scrise mai jos sunt echivalente. Ele afieaz datele nregistrate
pe coloana NUME.
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr[1]); }
rdr.Close();
Console.ReadLine();
sau
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open(); SqlCommand cmd = new SqlCommand("select * from
salar_angajat", co);
SqlDataReader rdr =cmd.ExecuteReader();
while (rdr.Read()) { Console.WriteLine(rdr["nume"]); }
rdr.Close();
Console.ReadLine();
217
Int32 var = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM SALAR_ANGAJAT",co);
var=(Int32) cmd.ExecuteScalar();
Console.WriteLine(var);
Console.ReadLine();
II.8.7.
Interogarea datelor
Pentru extragerea datelor cu ajutorul unui obiect SqlCommand trebuie s utilizm metoda
ExecuteReader care returneaz un obiect SqlDataReader.
// Instaniem o comand cu o cerere i precizm conexiunea
SqlCommand cmd = new SqlCommand("select salar from salar_angajat", co);
// Obinem rezultatul cererii
SqlDataReader rdr = cmd.ExecuteReader();
II.8.8.
Inserarea datelor
Pentru a insera date ntr-o baz de date utilizm metoda ExecuteNonQuery a obiectului
SqlCommand .
// irul care pstreaz comanda de inserare
string insertString = @"insert into salar_angajat(ID,NUME,PRENUME,VECHIME,SALAR)
values (6 ,'BARBU' ,'EUGENIU', 17,1993)";
// Instaniem o comand cu acest cerere i precizm conexiunea
SqlCommand cmd = new SqlCommand(insertString, co);
// Apelm metoda ExecuteNonQuery pentru a executa comanda
cmd.ExecuteNonQuery();
218
Exemplul 9: vom insera n tabela salar_angajat o nou nregistrare i vom afia tot coninutul
tabelei
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
try
{co.Open();
string insertString = @"insert into salar_angajat(ID ,NUME ,PRENUME
,VECHIME ,SALAR)values (6,'BARBU','EUGENIU',17,1993)";
SqlCommand cmd = new SqlCommand(insertString, co);
cmd.ExecuteNonQuery();}
finally
{if (co != null) { co.Close(); }}
SqlCommand comand = new SqlCommand("SELECT * FROM SALAR_ANGAJAT", co);
co.Open();
SqlDataReader reader = comand.ExecuteReader();
while (reader.Read())
Console.WriteLine(String.Format("\t{0}\t{1}\t{2} \t {3} \t {4}",
reader[0], reader[1], reader[2], reader[3], reader[4]));
Console.ReadLine();
reader.Close(); }
II.8.9.
Actualizarea datelor
Exemplul 10: vom modifica numele unui angajat, din BARBU n BIBIRE
SALAR_ANGAJAT i vom afia tot coninutul tabelei
n tabela
219
Exemplul 12: Realizai o conexiune la baza de date SALAR_ANGAJAT i afiai cea mai
mare vechime i suma tuturor salariilor nregistrate.
Int32 var = 0; Int32 suma = 0;
SqlConnection co = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");
co.Open();
SqlCommand comand1 = new SqlCommand("select MAX(VECHIME) FROM
SALAR_ANGAJAT",co);
var = (Int32)comand1.ExecuteScalar();
Console.Write(" CEA MAI MARE VECHIME A UNUI ANGAJAT ESTE DE :");
Console.Write(var); Console.WriteLine(" ANI");
SqlCommand comand2 = new SqlCommand("select SUM(SALAR) FROM
SALAR_ANGAJAT", co);
suma = (Int32)comand2.ExecuteScalar();
Console.Write(" SUMA SALARIILOR TUTUROR ANGAJATILOE ESTE: ");
Console.Write(suma); Console.WriteLine(" RON");
Console.ReadLine();
220
Exemplul 12: Realizai funcii care s implementeze operaiile elementare asupra unei
baze de date i verificai funcionalitatea lor.
conexiunea la baza de date
class program
{
SqlConnection conn;
public program()
{
conn = new SqlConnection("DATA SOURCE=DANAD90FDEF1A8\\SQLEXPRESS;Initial Catalog=SALARII;Integrated
Security=SSPI");}
apelarea din funcia main a funciilor care vor realiza afiarea datelor, inserarea unei noi
valori, tergerea unor valori, actualizare
static void Main()
{
program scd = new program();
Console.WriteLine("SALARII ANGAJATI");
scd.ReadData();
scd.Insertdata();
Console.WriteLine("AFISARE DUPA INSERT");
scd.ReadData(); scd.UpdateData();
Console.WriteLine("AFISARE DUPA UPDATE");
scd.ReadData(); scd.DeleteData();
Console.WriteLine("AFISARE DUPA DELETE");
scd.ReadData();
int number_inregistrari = scd.GetNumberOfRecords();
Console.WriteLine("Numarul de inregistrari: {0}",
number_inregistrari);
Console.ReadLine();
}
221
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(); } }
}
datele
datasetul
ds
sub
forma
unei
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
Fill() permite umplerea unei tabele dintr-un obiect DataSet cu date. Permite specificarea
obiectului DataSet n care se depun datele, eventual a numelui tablei din acest DataSet, numrul
de nregistrare cu care s se nceap popularea (prima avnd indicele 0) i numrul de nregistrri
care urmeaz a fi aduse.
Update() permite transmiterea modificrilor efectuate ntr-un DataSet ctre baza de date.
Un DataSet este format din Tables (colecie format din obiecte de tip
DataTable este compus la rndul lui
DataTable;
procesarea
datelor
din
DataSet
folosind
numele
tabelelor
stabilite
la
umplere,
224
parametru un adapter, pentru care vor fi construite comenzile. SqlCommandBuilder are nu poate
construi dect comenzi simple i care se aplica unui singur tabel. Atunci cnd trebui ca sa facem
comenzi care vor folosi mai multe tabele este recomandata construirea separat a comenzilor i
apoi ataarea lor adapterului folosind proprieti.
Popularea DataSet-ului se face dup ce am construit cele dou instane:
daSALAR.Fill (dsNUME, "NUME");
n exemplul urmtor va fi populat DataSet-ul dsNUME. Cel de-al doilea parametru (string)
reprezint numele tabelului (nu numele tabelului din baza de date, ci al tabelului rezultat n
DataSet) care va fi creat. Scopul acestui nume este identificarea ulterioar a tabelului. n cazul n
care nu sunt specificate numele tabelelor, acestea vor fi adugate n DataSet sub numele Table1,
Table2, ...
Un DataSet poate fi folosit ca surs de date pentru un DataGrid din Windows Forms sau
ASP.Net .
DataGrid dgANGAJAT = new DataGrid();
dgANGAJAT.DataSource = dsNUME;
dgANGAJAT.DataMembers = "NUME";
Dup ce au fost fcute modificri ntr-un DataSet acestea trebuie scrise i n baza de date.
Actualizarea se face prin apelul metodei Update.
daSALAR.Update (dsNUME, "NUME");
225
II.9.
Aplicaie final
Pentru a realiza aceast aplicaie trebuie s creai o baz de date (noi am numit-o
salarii) baz n care trebuie s creai o tabel (noi am anumit-o salar_angajat) cu cinci cmpuri (ID,
NUME, PRENUME, VECHIME, SALAR) pe care o putei popula cu cteva nregistrri.
Noi ne-am propus s crem o aplicaie care s:
- insereze una sau mai multe nregistrri,
- s tearg una sau mai multe nregistrri,
- s afieze permanent numrul de astfel de modificri efectuate,
- s afieze coninutul tabelei dup fiecare modificare,
- s calculeze suma salariilor din tabel
- s afieze cel mai mare salar
- s afieze cea mai mic vechime
- s afieze nregistrrile n ordine lexicografic
Pentru a realiza i voi acelai lucru va trebui s parcurgei paii explicai n continuare.
Din meniul File al aplicaiei Microsoft Visual C# 2008 Express Edition alegei New
Project/Windows Forms Application. Pe formular va trebui s tragei un buton (INSERARE), cinci
etichete(ID, NUME, PRENUME, VECHIME, SALAR), cinci casete de text poziionate sub fiecare
etichet, o etichet n care s introducei textul NUMR DE MODIFICRI, iar n dreptul ei o
caset de text. Urmrii imaginea din figura de mai jos:
n sursa din spatele formularului declarai o variabil de tip int nrmodificari care va contoriza
permanent numrul de modificri aduse tabelei (tergeri, inserri) i conexiunea la baza de date.
public partial class Form1 : Form
{
int nrmodificari = 0; SqlConnection co;
public Form1()
{
InitializeComponent();
226
co
=
new
SqlConnection(@"Data
D90FDEF1A8\SQLEXPRESS;Database=dana;Trusted_Connection=yes;");
co.Open();
}
Source=DANA-
Executai ciclk dublu pe butonul INSERARE i completai sursa lui cu instruciunile care
vor permite inserarea unor nregistrri noi n tabel. Numrul de inserri l vei putea vizualiza n
caseta de text asociat etichetei cu numele NUMR DE MODIFICRI.
private void button1_Click(object sender, EventArgs e)
{
string insertsql;
insertsql="insert into salar_angajat (id,nume,prenume,vechime,salar) values
('";insertsql+=textBox1.Text+"','"+textBox2.Text+"','"+textBox3.Text+"','"+textB
ox4.Text+"','"+textBox5.Text+"')";
SqlCommand cmd = new SqlCommand(insertsql, co);
nrmodificari = nrmodificari+cmd.ExecuteNonQuery();
textBox6.Text =Convert.ToString(nrmodificari);}
}
227
V ntoarcei acum pe formular n mod design, i mai adugai un buton pe care noi lam numit STERGERE, o etichet n care va trebui s introducei textul INTRODUCETI NUMELE
ANGAJATULUI CE TREBUIE STERS i o caset de text, pe care o vei poziiona n dreptul
etichetei.
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
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