sfarsit:
Console.WriteLine("Sfarsit"); }
3.Declararea unor constante locale:
EXEMPLU: static void main(){ const float pi =3.141592 }
4.Declararea unor variabile locale:
EXEMPLU: static void main(){ int a = 2,b = 3,c= 5; }
5.Instructiuni complexe de tip expresie:
EXEMPLU: apelul unei functii static int F(int a,int b){}
static void Main(){ F(3,5) }
6.Instructiunea conditionala IF:
EXEMPLU: if (x >y) { Console.WriteLine("x este mai mare decat y");}
7.Instructiunea alternativa Switch Case:
EXEMPLU: static void Main(string[] args){ switch (args.Length) {
case 0:
Console.WriteLine("zero");
case 1:
Console.Writeline("unu");
}}
8.Bucla conditionala WHILE:
EXEMPLU: static void Main(string[] args) { int i = 0;
while (i < args.Length) { Console.WriteLine(args[i]);
i++; }}
9.Bucla conditionala DO...WHILE:
EXEMPLU: static void Main() { string s;
do { s = Console.ReadLine(); }
while (s != "Exit"); }
10.Bucla de repetitie FOR:
EXEMPLU: static void Main(string[] args){
for (int i = 0;i < args.Length;i++)
Console.WriteLine(args[i]); }
11.Bucla de iteratie FOREACH:
parcurge toate elementele dintr-o colectie
-24-
EXEMPLU: static void Main( string[] args) {
foreach (string s in args)
Console.WriteLine(s); }
12.Iesirea dintr-o bucla prin BREAK:
EXEMPLU: static void Main() { int x = 5;
while(x < 30) { Console.WriteLine("{0}",x);
x++;
if (x > 10)
break; }}
13.Continuarea unei bucle dupa instructiunea CONTINUE:
EXEMPLU: static void Main(string[] args) {
int i = 0;
while(true) { Console.WriteLine(args[i++]);
if (i < args.Length) continue;
break; }}
14.Specificarea datelor returnate,prin RETURN:
EXEMPLU: static int F(int a,int b) { return a + b ; }
static void Main(){ Console.WriteLine(F(2,3)); return; }
15.Evaluarea unui iterator prin YIELD:
EXEMPLU: static IEnumerable FromTo(int a,int b) {
if ( a > b ) yield break;
for ( ; ; a++) { yield return a;
if (a == b) break; }}
16.Tratarea exceptiilor prin bucle TRY...CATCH:
EXEMPLU:
static int F(int a,int b){
if (b == 0 ) throw new Exception("Divide by zero");
return a / b; }
static void Main(){ try { Console.WriteLine(F(5,0)); }
catch(Exception e){Console.WriteLine("Error"); }}
17.Verificarea domeniului de valori prin operatorii CHECKED/UNCHECKED:
EXEMPLU: static void Main() { int x = Int32.MaxValue;
checked { Console.WriteLine(x+1); }
unchecked { Console.WriteLine(x+1); } }
18.Blocarea unui fir de executie (thread) prin LOCK:
EXEMPLU: lock (x) { DoSomething(); }
19.Alocarea de resurse prin instructiunea USING:
EXEMPLU: static void Main() { using (Resource r = new Resource()) }
Nu exista diferente esentiale fata de limbajul C++.Alegerea uneia sau
alteia dintre aceste instructiuni,depinde atat de contextul de memorie,
cat si de experienta anterioara a programatorului.In principiu,sunt de
preferat in aplicatiile simple de tip Consola,cu program de tip listing
si sunt de evitat in mediul vizual.In general,nu este recomandabil sa
utilizati bucle automate pentru crearea unor obiecte complexe,deoarece
este foarte greu de controlat alocarea memoriei si exista un risc crescut
de a bloca executia,prin supraincarcarea memoriei de operare.Trebuie sa
stiti,ca instructiunile de procesare au prioritate maxima in ordinea de
executie a procesorului si vor fi executate si atunci cand nu sunt
concepute corect.Este esential sa verificati cu maximum de atentie,toate
situatiile extreme ce pot fi generate de astfel de instructiuni.
-25-
CLASE SI OBIECTE
Programele mari,contin mult prea multe date,pentru a putea fi incluse
simultan in memoria procesorului.Pentru a putea procesa datele,este strict
necesar sa fie impartite in calupuri mai mici.Daca nu exista nici un fel
de structurare a programului,procesorul pur si simplu imparte datele in
functie de dimensiunea tamponului de memorie.In unele situatii insa,acest
mecanism poate duce la rezultate eronate sau aleatorii.Din acest motiv,
programatorii au inventat sisteme din ce in ce mai elaborate de organizare
a datelor,astfel incat fragmentarea programelor sa se faca doar in module
perfect functionale.Cea mai simpla solutie,o reprezinta impartirea codului
in mai multe file.Fiecare astfel de fila,va avea un nume propriu ( va fi
un spatiu denumit) si va putea fi incarcata separat in procesor.O alta
forma mai elaborata de structurare a datelor,este sub forma de containere
mai mult sau mai putin organizate,cum sunt:listele si enumerarile,tabelele
si bazele de date,ariile de date,structurile,clasele si obiectele.Un
astfel de container,nu numai ca are un nume propriu,dar contine si un set
oarecare de reguli fixe,pentru organizarea datelor.
Dintre aceste containere,clasele reprezinta forma cea mai complexa de
structurare a datelor.O clasa,este reprezentata prin setul de reguli fixe
ce urmeaza sa fie respectate in respectivul spatiu denumit.Clasa nu exista
propriu zis in program,ci este doar matrita pentru formarea unor entitati
reale,denumite obiecte.Un obiect este o instanta a unei clase si contine
atat indentificatorul spatiului denumit cat si datele propriu zise.In
procesor nu pot fi incarcate clase,ci doar obiectele create cu ajutorul
acestor clase.Pentru a tine evidenta lor,programul utilizeaza referinte
(pointeri spre adresa de memorie la care este arhivata definita lor).Se
poate spune despre clase ca sunt un tip de data,de tip referinta.
Clasele reprezinta un avantaj enorm pentru programator.Nu numai ca
izoleaza seturi de date si functii pentru procesarea lor,dar pot forma
module de program complet independente.Cu o singura referinta,procesorul
poate fi conectat la un intreg modul executabil.In momentul in care se
creaza un obiect,practic se creaza o referinta spre clasa sa de origine.
Toate aceste refernite sunt monitorizate de procesor,cu ajutorul unei
tabele de pointeri,astfel incat sa poata fi apelate,ori de cate ori este
necesar.In limbaj C#,intrega gestiune a memoriei se face automat.Nu mai
este necesar ca programatorul sa elibereze explicit memoria.Cu ajutorul
unui mecanism de tip "garbage collector" asemanator cu cel din Java (dar
cu implementare interna diferita),procesorul manipuleaza intern toate
obiectele si elibereaza pe cele inutile,dupa o secventa oarecare de
prioritati.Din acest motiv,este esential ca orice program C# sa fie
format din obiecte,sau componente.
Clasele pot mostenii definitii si declaratii de la alte clase,pot
impelemnta interfete si pot include date,sub forma de: constante,campuri
de date,variabile,metode si proprietati,evenimente si instructiuni.Dintre
metode,sunt esentiale constructorul si destructorul.Constructorul este o
functie mai speciala,ce se executa obligatoriu atunci cand se creeaza un
obiect,iar destructorul este o functie mai speciala ce se executa atunci
cand obiectul este eliberat din memorie.
Fiecare tip de data,poate fi precedat de urmatorii modificatori:
public,protected,internal,protected internal sau provate,pentru a preciza
domeniul de vizibilitate al datelor respective.
-26-
Cei cinci modificatori au urmatoarea semnificatie:
public -acces nelimitat
protected -acces limitat la clasa si clasele mostenitoare
internal -acces limitat la programul curent
internal protected -acces limitat in program si clasele mostenitare
private -acces limitat in tipul respectiv de data
Chiar daca sunt doar entitati virtuale,clasele trebuie sa fie definite
intr-o fila separata,denumita biblioteca cu alocare dinamica.Pentru a
crea un obiect,procesorul importa biblioteca DLL,citeste definitiile si
apoi creaza obiectul real.Deci,procesorul consuma memorie pentru a citi o
clasa.Acest fapt are importanta maxima,atunci cand creati astfel de file
de tip biblioteca DLL.Cu cat fila va fi mai mica,cu atat clasele continute
vor fi mai usor de importat.Este intotdeuna mai eficient sa creati mai
multe file mici,decat o singura biblioteca foarte mare.
Platforma Framework .Net contine un set extrem de bogat de astfel de
clase predefinite,arhivate in bibliotecile DLL standard.Pentru a crea un
obiect,este suficient sa fie importata biblioteca si sa fie apelat apoi
constructorul.
EXEMPLU:
using System;
using System.Windows.Forms;
namespace FereastraSimpla {
public class MyForm : System.Windows.Forms.Form {
public MyForm(){}
[STAThread]
static void Main(){ Application.Run(new MyForm()); }
}}
Salvati fila cu numele Clasa1.cs si compilati.
Se va produce un executabil ce deschide o fereastra Windows simpla.
Daca analizati putin codul,observati urmatoarele etape:
1. se importa bibliotecile sursa
2. se declara spatiul denumit (se fragmenteaza memoria)
3. se declara un obiect de tip Form (mostenit din clasa Windows.Forms)
4. se defineste constructorul clasei
5. se declara functia Main in care se apeleaza constructorul clasei
Expresia [STAThread] este facultativa si are rost pentru mecanismul de
"garbage collector" (seteaza prioritatea thread-ului).
Exemplul de mai sus,creaza un obiect standard,fara nici un fel de date
personalizate.Pentru a dezvolta obiectul,se pot adauga constante,campuri
de date,metode,proprietati si evenimente.Toate aceste date,pot fi complet
noi,caz in care trebuie sa contina atat declaratia cat si o definitie cat
mai amanuntita,sau pot fi creata cu ajutorul unor biblioteci standard,sau
al unor biblioteci DLL predefinite de d-voasta.
In majoritatea situatiilor moderne,se prefera obiectele vizuale
definite in biblioteca System.Windows.Forms.Pentru obiectele vizuale,se
prefera termenul de componente,preluat de la interfata de lucru vizuala,
in care crearea unui astfel de obiect se face cu un simplu click de mouse.
De fapt sunt obiecte obinuite,create cu ajutorul unor clase predefinite,
dar apelul constructorului se poate face si automat.Toate componentele
vizuale au un set foarte bogat de proprietati si metode standard,ce
rezolva toate necesitatile obisnuite de programare.
-27-
De exemplu,pentru a adauga un text in fereasta,se poate include si un
component de tip Label.Obiectul trebuie declarat,construit,setat si apoi
inclus in containerul de baza (in obiectul Form).
EXEMPLU:
using System;
using System.Windows.Forms;
namespace FereastraSimpla2 {
public class MyForm : System.Windows.Forms.Form {
private System.Windows.Forms.Label label1;
public MyForm(){ InitializeComponent(); }
private void InitializeComponent() {
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(101,48);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(46,13);
this.label1.TabIndex = 0;
this.label1.Text = "Textul dorit";
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
[STAThread]
static void Main(){ Application.Run(new MyForm()); }
}}
Salvati fila cu numele Clasa2.cs si compilati.
Observati ca fata de exemplul precedent,au aparut si urmatoarele etape
suplimentare:
1. se declara un obiect de tip Label,numit label1
2. constructorul apeleaza o metoda speciala (InitializeComponent)
3. in functia de initializare se executa:
-se construieste obiectul label1 (apel constructor)
-se seteaza proprietatile
-se include label in in MyForm
-se seteaza proprietatile pentru MyForm
-se actualizeaza aspectul ferestrei
In acest exemplu am pastrat organizarea creata automat de platforma
Visual C# (practic am extras codul sursa),pentru a evidentia faptul ca
nu exista diferente esentiale intre compilatorul csc.exe si cel inclus
in platforma vizuala.Programarea cu componente vizuale se poate invata
si scriind coduri,linie cu linie.Acest gen de studiu va facilita foarte
mult orice operatie de depanare a codurilor.
In exemplul de mai sus,cuvantul cheie "this" este pointerul spre
instanta respectiva a obiectului.In lipsa sa,ar fi trebuit construit un
obiect explicit: object1 = new MyForm() si apoi fiecare component ar
fi trebuit sa fie referit prin: obiect1.label1 ...etc.
Constructorul va putea contine,una sau mai multe astfel de functii de
initializare,in functie de complexitatea interfetei grafice.
-28-
Orice variabila declarata in definitia unei clase,formeaza un membru
al clasei,denumit "camp de date" (field),pentru a se deosebi de orice
alta variabila simpla declarata la nivel de obiect.Si in interiorul
obiectelor,vor fi denumite tot "campuri de date",pentru a se diferentia
de variabilele simple(cele care exista doar in instanta respectiva).
Exista si un tip special de astfel de campuri de date,pentru care
se declara cate o metoda specializata Set() si Get(),astfel incat sa
poata accepta sau sa poata returna valoarea continuta.Acest tip special
de campuri de date,poarta numele de proprietati.
EXEMPLU: public class ButonulMeu {
private string caption;
public string Caption {
get { return caption; }
set { caption = value;
Repaint(); }
}}
In exemplul de mai sus,variabila de tip string "caption" este o
proprietate a clasei,deoarece poate fi setata cu set(),sau poate returna
valoarea continuta,cu get().Proprietatile sunt folosite extensiv,mai ales
pentru obiectele vizuale,deoarece permit utilizarea unor rutine automate
pentru setarea lor.Are rost sa definiti astfel de proprietati,mai ales
atunci cand oferiti si o intefata vizuala,prin care utilizatorul poate
interactiona cu obiectul cu un simplu click de mouse.
Interactiunea dintre utilizator si interfata grafica se face prin
intermediul unor mecanisme de control,denumite evenimente.Sistemul de
operare (Windows) emite cate un mesaj,pentru fiecare operatie de tip I/O
sau actiune executata de utilizator (vezi mesajele Windows).In Pascal,
aceste mesaje sunt asteptate si interceptate de functia GetMessage().In
Java,mesajele sunt interceptate si prelucrate de obiecte "listener",iar
in limbajul C#,au fost introduse niste clase speciale,denumite clase
"delegate".O astfel de clasa,contine si o referinta directa spre metoda
de tratare a evenimentului.Obiectul care emite mesajul,se numeste si
expeditor (event sender),iar cel care receptioneaza mesajul si apoi
prelucreaza solutia de raspuns,poarta numele de receptor (event reciver).
Biblioteca System,contine o clasa delegat,denumita EventHandler,destinata
anume pentru interceptarea si tratarea mesajelor Windows.
Pentru a programa un eveniment complet,sunt necesare trei etape:
1. -se declara un obiect de tip EventHandler ce contine o referinta
spre functia de tratare a evenimentului.
2. -se defineste functia de tratare a evenimentului
3. -se asociaza obiectul EventHandler la obiectul sender (cel care emite
mesajul Windows).
Nu se pot construi chiar orice fel de evenimente,decat daca definiti
si o functie specializata sa emita un eveniment oarecare.Componentele
vizuale (cele din System.Windows.Forms) au fiecare cate un grup de
mesaje standard,ce pot fi exploatate pentru a declansa evenimente.Daca
utilizati platforma Visual C#,acestea sunt prezentate sub forma de lista
in fereastra Properties / Events.Daca editati codurile manual,trebuie sa
studiati cu atentie bibliografia fiecarui obiect.
Cel mai simplu eveniment,dintr-o interfata vizuala este cel declansat
de apasarea unui buton.
-29-
EXEMPLU:
using System;
using System.Windows.Forms;
namespace ButonulMeu {
public class MyForm : System.Windows.Forms.Form{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
public MyForm(){ InitializeComponent(); }
private void InitializeComponent(){
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
// se seteaza label1
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(101,48);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(46,13);
this.label1.TabIndex = 0;
this.label1.Text = "Eticheta";
// se seteaza button1
this.button1.Location = new System.Drawing.Point(104,94);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75,23);
this.button1.TabIndex = 1;
this.button1.Text = "Apasa butonul";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
// se seteaza Form1
this.AutoScaleDimensions = new System.Drawing.Size(6F,13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292,266);
this.Controls.Add(this.button1);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private void button1_Click(object sender,EventArgs e)
{ label1.Text = "Butonul a fost apasat"; }
[STAThread]
static void Main(){ Application.Run(new MyForm()); }
}}
Salvati fila cu numele Clasa3.cs si compliati.
In exemplul de mai sus,se executa simultan doua operatii: se creaza un
obiect de tip System.Event.Handler (pentru evenimentul button1_Click) si
se asociaza acest obiect butonului button1,cu ajutorul operatorului +=
(se adauga metoda in lista de metode a obiectului button1).
Apoi se declara functia pentru tratarea evenimentului button1.Click().
Obiectul receptor si functia de tratare a evenimentului au acelasi nume,
pentru a putea fi identificate cat mai usor.
-30-
Un exemplu similar poate fi rezumat astfel:
EXEMPLU:
using System;
using System.Windows.Forms;
using System.Drawing;
public class Mousedemo:System.Windows.Forms.Form {
public Mousedemo() {
this.MouseUp += new MouseEventHandler(OnMouseup);
}
public void OnMouseup(object sender,MouseEventArgs e) {
this.Text = "Pozitia curenta este: (" +e.X +"," +e.Y +")";
}
public static void Main() {
Application.Run(new Mousedemo());
}
}
Salvati fila cu numele Clasa4.cs si compilati.Lansati programul si
executati cateva click-uri de mouse in fereastra.Se va afisa pozitia (pe
bara de titlu a ferestrei).
In acest caz,se creaza un MouseEventHandler (pentru mesajul OnMouseUp)
si se asociaza obiectului MouseDemo (cel construit prin apelul metodei
constructor).Apoi se declara functia de raspuns la mesaj.Acest mecanism,
este mai greu de inteles decat de implementat.Pur si simplu,puteti aplica
aceasta solutie,pentru orice mesaj Windows.De exemplu,pentru a identifica
apasarea unei taste oarecare,se poate aplica algoritmul:
EXEMPLU:
using System;
using System.Windows.Forms;
using System.Drawing;
public class Keydemo: System.Windows.Forms.Form {
public Keydemo {
this.KeyUp += new KeyEventHandler(OnKeypress);
}
public void OnKeypress(object sender,KeyEventArgs e) {
MessageBox.Show(e.KeyCode.ToString(),"Tasta apasata:");
}
public static void Main() {
Application.Run(new Keydemo());
}
}
Salvati fila cu numele Clasa5.cs si compilati.Lansati programul si
apoi apasati orice tasta.
Observati ca metoda de tratare a evenimentului are si doi parametri:
object sender si EventArgs e.Primul desemneaza obiectul care emite
mesajul Windows,iar cel de al doilea desemneaza obiectul receptor (cel
care interceptreaza mesajul Windows).
Cand programul contine un singur obiect,cu un singur eveniment,nu
exista nici un risc pentru interactiuni nedorite.In mod normal insa,o
interfata grafica contine numeroase obiecte similare,ce emit mesaje
Windows similare.Cei doi parametri au rostul de a face distinctia dintre
-31-
doua mesaje similare,emise de obiecte diferite.In Pascal,toate mesajele
emise de sistem se aduna intr-o stiva,de unde sunt evaluate si prelucrate
in ordinea sosirii.Cu cat sunt mai multe evenimente,cu atat timpul de
asteptare este mai lung si apare riscul de a interfera cu mesaje emise de
un alt obiect.In mediul C#,acest tip de accident nu este posibil,deoarece
se specifica explicit,atat obiectul sender,cat si obiectul receptor.
Clasele de tip delegat,permit o flexibilitate de programare mult mai
mare,decat ascultatorii din Java.Astfel,un eveniment oarecare poate fi
conectat cu mai multe functii de tratarea evenimentului,ce pot fi
declansate simultan sau un cascada.Deasemenea,este posibil ca mai multe
evenimente sa fie conectate la aceeasi functie de raspuns.Exemplu: se va
obtine acelasi raspuns,la un click de mouse cu butonul drept,sau cu
butonul stang,sau prin apasarea tastei Enter.
In plus,clasa delegat nu intercepteaza decat strict mesajul dorit.Toate
celelalte mesaje sunt filtrate.Ca rezultat,nu exista o lista de asteptare
si nici riscul de a declansa metoda de raspuns pentru un mesaj eliberat
de un alt obiect.
Modul in care sunt alese si combinate evenimentele din interfata,face
obiectul unei profesiuni de sine statatoare (web designer) si nu poate
fi prezentat exhaustiv intr-un abecedar.In principiu,se vor alege doar
evenimentele cele mai clare,indispensabile pentru executia programului.
Facultativ,programatorul poate adauga si mici evenimente "secrete" cu
rostul de a facilita depanarea programului,sau de a oferii diverse
"artificii de programare",cu conditia ca aceste instrumente ajutatoare
sa nu interfereze cu executia normala a programului.
Pentru a creste,sau diminua numarul de mesaje ce pot fi emise de catre
obiectul sender,programatorul poate declara niste functii speciale,prin
care adauga sau elimina mesajele Windows din lista obiectului.
EXEMPLU: public class Panel1 {
private EventHandler handler;
public event EventHandler Click {
add { handler += value; }
remove { handler -= value; }
Dostları ilə paylaş: |