Sunteți pe pagina 1din 20

Ingineria programrii Laboratorul 2

Stilul de scriere a codului. Tratarea excepiilor


Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm
1. Obiective 2. Stilul de scriere a codului 3. Tratarea excepiilor 4. Interfaa grafic cu utilizatorul n Microsoft Visual Studio .NET 5. Elemente de C# 6. Aplicaii

1. Obiective
Obiectivele laboratorului 2 sunt urmtoarele: Sublinierea importanei unui stil unitar de scriere a codului ntr-o firm de dezvoltare de software; Descrierea standardului de scriere a codului pe care l vom utiliza la laboratoarele de IP; Explicarea modalitilor de tratare a excepiilor n C#; Reamintirea unor aspecte legate de dezvoltarea de aplicaii cu interfa grafic; Reamintirea modului de lucru cu proprieti C#.

2. Stilul de scriere a codului


Unul din scopurile urmrite la scrierea de programe trebuie s fie ntreinerea ulterioar a codului, adic facilitarea modificrilor i completrilor viitoare, foarte probabil de ctre persoane diferite dect autorul iniial. De asemenea, unele studii au artat c dup 6 luni de la scrierea unui program, acesta i apare la fel de strin autorului ca i un program scris de altcineva. Unul din aspectele principale ale codului uor de ntreinut este posibilitatea de a gsi anumite buci de cod i de a le modifica fr a afecta celelalte seciuni. Claritatea este esenial. Altfel, n cazul programelor de mari dimensiuni, aa cum sunt majoritatea situaiilor n software-ul industrial, n loc s adugai funcionaliti i s lucrai efectiv, vei pierde timpul ncercnd s gsii poriunile relevante de cod care trebuie modificate. Formatarea codului poate simplifica nelegerea structurii semantice sau poate cauza confuzie. Poate chiar ascunde defecte greu de depistat, de exemplu:
bool error = DoSomething(); if (error) Console.WriteLine("Eroare"); Environment.Exit(1);

Nu conteaz ct de bine este proiectat un program; dac prezentarea sa arat neglijent, va fi neplcut de lucrat cu el.

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

2.1. Acoladele
Exist dou tipuri principale de plasare a acoladelor. Stilul Kernighan i Ritchie este bazat pe dorina de a afia ct mai mult informaie ntr-un mod compact:
int KernighanRitchie() { int a = 0, b = 0; while (a != 10) { a++; b--; } return b; }

Acest stil poate fi folosit la prezentri de cod sau n situaii n care spaiul disponibil pentru afiarea codului este redus, de exemplu ntr-un material tiprit. Stilul extins sau stilul Allman este recomandat de Microsoft pentru limbajul C#:
int Extended() { int a = 0, b = 0; while (a != 10) { a++; b--; } return b; }

Avantajul principal al acestuia este claritatea, deoarece blocurile de cod sunt evideniate prin alinierea acoladelor. Este stilul pe care l vom utiliza la laboratorul de IP.

2.2. Standarde de programare


Muli programatori fr experien industrial, dei foarte buni, refuz la nceput aplicarea unor standarde impuse. Dac programul este corect, de ce trebuie s l aliniez altfel sau s schimb numele variabilelor sau metodelor? Trebuie avut n vedere faptul c nu exist un stil perfect, deci rzboaiele privind cea mai bun formatare nu pot fi ctigate. Toate stilurile au argumente pro i contra. Majoritatea firmelor serioase de software au standarde interne de scriere a programelor, care definesc regulile pentru prezentarea codului. Aceste standarde cresc calitatea programelor i sunt importante deoarece toate proiectele livrate n afara organizaiei vor avea un aspect ngrijit i coerent, de parc ar fi fost scrise de aceeai persoan. Existena mai multor stiluri distincte ntr-un proiect indic lipsa de profesionalism. Faptul c un programator crede c stilul su propriu este cel mai frumos i cel mai uor de neles nu are nicio importan. Un stil care unui programator i pare n mod evident cel mai bun poate reprezenta o problem pentru altul. De exemplu:

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Acest program a fost aliniat folosind opiunile din mediul Visual Studio: Tools Options Text Editor C# Formatting, nu a fost aliniat aleatoriu. n acelai mod, stilul personal al unui programator poate prea la fel de ciudat altuia. Beneficiile adoptrii unui stil unitar de ctre toi membrii unei organizaii depete dificultile iniiale ale adaptrii la un stil nou. Chiar dac nu suntei de acord cu standardul, trebuie totui s v confomai. Dup ce vei folosi un timp stilul firmei, v vei obinui cu el i v va prea perfect natural. La laboratorul de IP vom utiliza un standard bazat pe recomandrile Microsoft pentru scrierea programelor C#. Se recomand delimitarea regiunilor de program cu ajutorul cuvntului cheie region, de exemplu:
#region Fields private View _view; private DataModel _dataModel; #endregion

Dac toate seciunile unei clase sunt delimitate pe regiuni, pagina ar trebui s arate n felul urmtor atunci cnd toate definiiile sunt colapsate:

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

using System . Windows . Forms; namespace LabIP { public class HelloWorld:System . Windows . Forms . Form { public HelloWorld ( ) { InitializeComponent ( ); } protected override void Dispose ( bool disposing ) { if( disposing ) { if( components != null ) { components . Dispose ( ); } } base . Dispose ( disposing ); } static void Main ( ) { Application . Run ( new HelloWorld ( ) ); } private void button1_Click ( object sender , System . EventArgs e ) { string STRING = "Hello World!"; display ( STRING ); } private void display ( string STR ) { MessageBox . Show ( STR , ":-)" ); } } }

2.3. Convenii pentru nume


Cheia alegerii unor nume potrivite este nelegerea rolului construciei respective. De exemplu, dac nu putei gsi un nume bun pentru o clas sau o metod, tii la ce folosete sau chiar trebuie s existe n program? Dificultile la alegerea unui nume potrivit pot indica probleme de proiectare. Un nume trebuie s fie: Descriptiv: Oamenii i pstreaz deseori percepiile iniiale asupra unui concept. Este important deci crearea unei impresii iniiale corecte despre datele sau funcionalitile unui program prin alegerea unor termeni care s descrie exact semnificaia i rolul acestor. Numele trebuie alese din perspectiva unui cititor fr experien, nu din perspectiva proprie; Adecvat: Pentru a da nume clare, trebuie s folosim cuvinte din limbajul natural. Programatorii au tendina de a utiliza abrevieri i prescurtri, ns acest lucru conduce la denumiri confuze. Nu are importan faptul c un identificator este lung dac este lipsit de ambiguitate. st nu este o alegere potrivit pentru conceptul NumarStudenti. Regula de urmat este: preferai claritatea fa de laconism. Excepiile sunt contoarele de bucle, de exemplu clasicul for (int i = 0; i < length; i++). Acestea de multe ori nu au o semnificaie de sine stttoare, sunt construcii specifice (idiomuri) ale limbajelor evoluate din C i de obicei se noteaz cu o singur liter: i, j, k etc.; Consecvent: Regulile de numire trebuie respectate n tot proiectul i trebuie s se conformeze standardelor firmei. O clas precum cea de mai jos nu prezint nicio garanie de calitate:
class badly_named : MyBaseClass { public void doTheFirstThing(); public void DoThe2ndThing(); public void do_the_third_thing(); }

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Pentru descrierea tipurilor de nume, exist n englez o serie de termeni care nu i au un echivalent exact n limba romn: Pascal case: Primul caracter al tuturor cuvintelor este o majuscul iar celelalte caractere sunt minuscule. De exemplu: NumarStudenti; Camel case: Pascal case cu excepia primului cuvnt, care ncepe cu liter mic. De exemplu: numarStudenti.

Pentru numirea conceptelor dintr-un program C#, vom adopta urmtoarele convenii: Concept Namespace-uri Clase Interfee Metode Variabile locale Variabilele booleene Parametrii metodelor Cmpuri private 1 Proprieti 2 Constante, cmpuri readonly publice 3 Controale pentru interfaa grafic 4 Excepiile
1

Convenie Pascal case Pascal case Pascal case precedat de I Pascal case Camel case Prefixate cu is Camel case Camel case precedat de underscore Pascal case Pascal case Camel case precedat de tipul controlului Pascal case cu terminaia Exception

Exemple
namespace LaboratorIP class HelloWorld interface IEntity void SayHello() int totalCount = 0; bool isModified; void SayHello(string name) string _address; Address const int MaxSpeed = 100; buttonOK checkBoxTrigonometric comboBoxFunction MyException PolynomialException

Pn la versiunea Visual Studio 6.0, programatorii utilizau n C++ notaia maghiar a lui Simonyi pentru variabile, care indica i tipul acestora, de exemplu nAge pentru int. Pentru variabilele membre se folosea prefixul m_, de exemplu m_nAge. Pentru limbajul C#, Microsoft nu mai recomand utilizarea acestor notaii. Pentru cmpurile private exist cteva avantaje la prefixarea cu underscore: cmpurile clasei vor avea o notaie diferit de variabilele locale; cmpurile clasei vor avea o notaie diferit de parametrii metodelor, astfel nct se vor evita situaiile de iniializare de genul this.x = x, unde this.x este cmpul iar x este parametrul metodei; n IntelliSense, la apsarea tastei _ vor aprea grupate toate cmpurile. Avantajul utilizrii acestei convenii se manifest mai ales n situaii precum aceea de mai jos:
private int description; // ortografie corect public Constructor(int descripton) // ortografie incorect pentru "description" { this.description = description; // ortografie corect n ambele pri, cmpul rmne 0 }
2 3 4

Proprietile vor fi detaliate n seciunea opional 5.2. n mare, tot ce e public ntr-o clas trebuie s nceap cu liter mare

Aceast notaie are avantajul c dei numele sunt mai lungi, sunt lipsite de ambiguitate. Exist i stilul prefixrii cu o abreviere de 3 litere, de exemplu btn pentru button, ckb pentru checkbox etc. Pentru controale mai puin uzuale, semnificaiile prefixelor nu mai sunt evidente: pbx, rdo, rbl etc.

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

3. Tratarea excepiilor
Tratarea erorilor se fcea n C prin returnarea unei valori, de obicei int, care semnfica un cod de eroare. De exemplu, dac o funcie trebuia s deschid un fiier, ea putea ntoarce 0 dac totul a funcionat normal, respectiv codul de eroare 1 dac fiierul nu exista. n funcia apelant, programatorul trebuia s trateze codul returnat:

Cu toate acestea, programatorul era liber s apeleze funcia direct, OpenFile(s), fr a mai testa valoarea returnat. Programul putea fi testat cu succes, deoarece fiierul exista, ns putea s nu mai funcioneze dup livrare. Majoritatea funciilor Windows API returneaz un cod dintr-o list cu sute valori posibile, ns puini programatori testeaz aceste valori individual. Tratarea excepiilor a aprut pentru a da posibilitatea programelor s surprind i s trateze erorile ntr-o manier elegant i centralizat, permind separarea codului de tratare a erorilor de codul principal al programului, ceea ce face codul mai lizibil. Astfel, este posibil tratarea: tuturor tipurilor de excepii; tuturor excepiilor de un anume tip; tuturor excepiilor de tipuri nrudite.

Odat ce o excepie este generat, ea nu poate fi ignorat de sistem. Funcia care detecteaz eroarea poate s nu fie capabil s o trateze i atunci se spune c arunc (throw) o excepie. Totui, nu putem fi siguri c exist un caz de tratare pentru orice excepie. Dac exist o rutin potrivit, excepia este tratat, dac nu, programul se termin. Rutinele de tratare a excepiilor pot fi scrise n diverse feluri de exemplu, ele examineaz excepia i apoi nchid programul sau re-arunc excepia. Structura blocurilor try-catch pentru tratarea excepiilor este urmtoarea:
FunctieApelata { ... if (condiii) throw ... ... } FunctieApelanta { ... try { FunctieApelata(); } catch (Exception e) // catch fr parametru dac nu intereseaz detaliile excepiei { // prelucrri determinate de excepie (se testeaz valoarea lui e) } ... }

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

int err = OpenFile(s);

Codul care ar putea genera o excepie se pune n blocul try. Excepia este aruncat (thrown) n blocul try din funcia care a fost apelat (direct sau indirect). Erorile sunt verificate ntotdeauna n mod explicit. Un bloc try poate prea c nu conine rutine de tratarea erorilor, dar codul din interior poate determina execuia verificrilor. Excepiile care se petrec n blocul try sunt captate n mod normal de blocul catch care urmeaz imediat dup blocul try. Un bloc try poate fi urmat de 1 sau mai multe blocuri catch. Dac se execut un try i nu se lanseaz nicio excepie, toate rutinele de tratare sunt ignorate. Execuia se reia de la prima instruciune de dup ultima rutin de tratare. n C#, tipul trimis ca parametru este de obicei Exception:
try { FunctieApelata(); } catch (Exception ex) { ... }

De cele mai multe ori, ne intereseaz proprietatea Message (de tip string) a unui astfel de obiect, care arat cauza erorii. Textul respectiv este precizat n funcia care arunc excepia.
private void FunctieApelata(int a) { if (a == 0) throw new Exception("Argument zero"); } private void FunctieApelanta() { FunctieApelata(0); }

Dac excepia nu este tratat, va aprea un mesaj de atenionare cu textul dorit.

Mesajul de eroare trebuie preluat n program n blocul catch:


private void FunctieApelanta() { try { FunctieApelata(0); } catch (Exception ex) { // ex.Message este "Argument zero" } } 7

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Programatorul i poate defini propriile tipuri de excepii, n cazul n care are nevoie s trimit informaii suplimentare privind excepia. Acestea trebuie ns derivate din clasa Exception:
public class MyException: Exception { public int p; // informaie suplimentar // n constructor se apeleaz i constructorul clasei de baz public MyException(int val): base() { p = val; } }

Utilizarea acestui tip se face astfel:


throw new MyException(3);

Dup un try pot exista mai multe blocuri catch. Ele trebuie dispuse n ordinea invers a derivrii tipurilor (de la particular la general):
try { FunctieApelata(x); } catch (MyException me) { ... } catch (Exception ex) { ... }

Alt ordine nu este permis, eroarea fiind descoperit la compilare: A previous catch clause already catches all exceptions of this or a super type ('System.Exception').

3.1. Tratarea excepiilor pe thread-ul aplicaiei


Uneori pentru a fi siguri c nu am lsat vreo excepie netratat, putem trata global toate excepiile aprute pe firele de execuie ale aplicaiei, n maniera descris n continuare:
static class Program { static void Main() { // Adaugarea unui event handler pentru prinderea exceptiilor din firul principal al interfetei utilizator Application.ThreadException += new ThreadExceptionEventHandler(OnThreadException); // Adaugarea unui event handler pentru toate firele de executie din appdomain cu exceptia firului principal UI AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler( CurrentDomain_UnhandledException); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FormX()); // FormX este fereastra principala a programului } 8

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

// Trateaza exceptiile din firul principal UI static void OnThreadException(object sender, ThreadExceptionEventArgs t) { // Afiseaza detaliile exceptiei MessageBox.Show(t.Exception.ToString(), "OnThreadException"); } // Trateaza exceptiile din toate celelate fire de executie static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { // Afiseaza detaliile exceptiei MessageBox.Show(e.ExceptionObject.ToString(), "CurrentDomain_UnhandledException"); } }

4. Interfaa grafic cu utilizatorul n Microsoft Visual Studio .NET


Cnd este creat un nou proiect C# de tip Windows Application, n mijlocul ecranului, apare un formular (Form) fereastra principal a programului, n care se vor aduga diverse componente de control: butoane, textbox-uri etc.:

n partea din stnga a ecranului exist un toolbar (View Toolbox, Ctrl+Alt+X) din care se vor alege cu mouse-ul componentele ce vor fi adugate n fereastr. Pentru adugarea unei componente, programatorul va face click cu mouse-ul pe imaginea corespunztoare din toolbox, apoi va face click n form, n locul unde dorete s apar componenta respectiv. Odat introduse n fereastr, componentele pot fi mutate, redimensionate, copiate sau terse. n dreapta este o fereastr de proprieti (View Properties Window, F4). De aici, fiecrei componente folosite i se pot modifica proprietile, adic aspectul exterior, aa cum va aprea n program. De asemenea, se pot selecta evenimentele corespunztoare componentei care vor fi tratate n program.
9

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

n continuare, vor fi prezentate cteva componente de control folosite practic n orice program Windows. Pentru fiecare component, vor fi amintite unele proprieti i metode uzuale. Pentru o descriere mai amnunit, se recomand consultarea documentaiei MSDN. Application Clasa Application ncapsuleaz o aplicaie Windows. Clasa nglobeaz metode i proprieti statice pentru managementul unei aplicaii, cum ar fi metode pentru pornirea i oprirea programului, prelucrarea mesajelor Windows i proprieti corespunztoare informaiilor despre aplicaie. Se poate observa c n scheletul de program creat implicit de mediul de dezvoltare, n Main(), este pornit programul pe baza clasei corespunztoare ferestrei principale:
Application.Run(new Form1());

Form Clasa System.Windows.Forms.Form corespunde unei ferestre standard. O aplicaie poate avea mai multe ferestre una principal, cteva secundare i cteva ferestre de dialog. Cteva proprieti:
Icon icoana care apare n bara de titlu a ferestrei FormBorderStyle nfiarea i comportamentul border-ului (de exemplu, dac

fereastra poate fi redimensionat) Text titlul ferestrei, care apare n bara de titlu i n taskbar StartPosition locul unde apare fereastra pe ecran Size dimensiunea (nlimea i limea ferestrei); de obicei se stabilete prin redimensionarea ferestrei cu mouse-ul, n procesul de proiectare

Cteva evenimente:
Load, Closed pentru diverse iniializri n momentul crerii ferestrei sau prelucrri n

momentul nchiderii acesteia n general, pentru tratarea unui eveniment n C#, este selectat mai nti obiectul de tipul dorit (la noi fereastra), apoi n fereastra de proprieti se alege tab-ul de evenimente i se identific evenimentul cutat.

10

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Dup un dublu-click, ca n figura de mai sus, se va crea automat o nou funcie vid corespunztoare evenimentului, iar utilizatorul va trebui numai s scrie n corpul funciei aciunile dorite. Button Clasa System.Windows.Forms.Button corespunde unei buton. Cteva proprieti i evenimente: Label Clasa System.Windows.Forms.Label nscrie un text undeva n fereastr. Una din proprieti:
Text textul nscris Text textul nscris pe buton Click funcia executat cnd butonul este apsat

TextBox Clasa System.Windows.Forms.TextBox corespunde unei csue de editare de text. Cteva proprieti i evenimente:
Text textul din csu (de tip string) Multiline textul poate fi introdus pe o singur linie (false) sau pe mai multe (true) ScrollBars indic prezena unor bare de derulare (orizontale, verticale) dac proprietatea Multiline este true Enabled componenta este activat sau nu (true / false) ReadOnly textul din editbox poate fi modificat sau nu de utilizator (true / false) CharacterCasing textul poate aprea normal (Normal), numai cu litere mici (Lower)

sau numai cu litere mari (Upper) TextChanged funcie de tratare a textului n timp real, pe msur ce acesta este introdus

ComboBox Clasa System.Windows.Forms.ComboBox corespunde unui combo-box, care combin un textbox cu o list. Cteva proprieti i evenimente:
Text textul din partea de editare Items lista de obiecte din partea de selecie, care se poate introduce i prin intermediul

ferestrei de proprieti SelectedIndex numrul articolului din list care este selectat (0 primul, 1 al doilea, etc., 1 dac textul din partea de editare nu este ales din list) TextChanged, SelectedIndexChanged metode de tratare a schimbrii textului prin introducerea direct a unui nou cuvnt sau prin alegerea unui obiect din list

11

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

MenuStrip Clasa System.Windows.Forms.MenuStrip corespunde meniului principal al unei ferestre. Mod de folosire: se introduce o component de acest tip n fereastr se editeaz meniul, direct n fereastr sau folosind proprietile pentru separatori se introduce n cmpul Caption un minus ( ) literele care se vor subliniate vor fi precedate de & pentru implementarea metodei de tratare a unei opiuni din meniu se va face dublu-click pe aceasta (sau pe evenimentul Click n fereastra de proprieti).

Timer Clasa System.Windows.Forms.Timer ncapsuleaz funciile de temporizare din Windows. Cteva proprieti i evenimente: string Aceasta este o clas care permite multiple faciliti pentru lucrul cu iruri de caractere. Astfel, exist operatorul +, care permite concatenarea irurilor:
string str1 = "Microsoft "; string str2 = "Word"; str1 = str1 + str2; // sau str1 += str2; => str1 == Microsoft Word

Interval intervalul de timp (n milisecunde) la care va fi executat o funcie Enabled indic dac timer-ul e activat sau nu (true/false) Tick evenimentul care va fi tratat o dat la un interval de timp

Clasa conine multe proprieti i metode utile, dintre care amintim:


int Length lungimea irului int IndexOf(...) poziia n ir la care apare prima dat un caracter sau un subir string Substring(...) returneaz un subir string Remove(int startIndex, int count) returneaz irul rezultat prin

tergerea a count caractere din ir, ncepnd cu poziia startIndex string[] Split(...) mparte irul n mai multe subiruri delimitate de anumite secvene de caractere

O metod static a clasei este Format(...), care returneaz un ir de caractere corespunztor unui anumit format. Sintaxa este asemntoare cu cea a funciei printf din C. De exemplu:
double d = 0.5; string str = string.Format("Patratul numarului {0} este {1}", d, d*d);

Acelai rezultat s-ar fi putut obine astfel:


str = "Patratul numarului " + d.ToString() + " este " + (d*d).ToString();

12

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Orice obiect are metoda ToString(), care convertete valoarea sa ntr-un ir. Pentru obiecte definite de programator, aceast metod poate fi suprascris. Dac n exemplul de mai sus d = 0.72654 i dorim s afim numerele numai cu 2 zecimale, metoda Format i dovedete utilitatea:
string str=string.Format("Patratul numarului {0:F2} este {1:F2}", d, d*d); MessageBox.Show(str);

StringBuilder Majoritatea programatorilor utilizeaz ntotdeauna clasa string cnd opereaz cu iruri de caractere. n cazul concatenrii unor iruri, folosirea clasei StringBuilder aduce o important cretere de performan. S considerm urmtorul bloc:
string listaNumere = ""; for (int i=0; i<1000; i++) listaNumere = listaNumere + " " + (i+1).ToString();

n acest caz, se creeaz un nou obiect string la fiecare atribuire, adic de 1000 de ori! Codul echivalent folosind StringBuilder este urmtorul:
StringBuilder sbListaNumere = new StringBuilder(10000); for(int i = 0; i<1000; i++) { sbListaNumere.Append(" "); sbListaNumere.Append((i+1).ToString()); } string listaNumere2 = sbListaNumere.ToString();

Pentru a avea acces la clasa StringBuilder, trebuie inclus namespace-ul System.Text la nceputul programului:
using System.Text;

Aceste directive using sunt asemntoare directivelor #include din C/C++. Namespace-urile sunt colecii de clase predefinite sau definite de programator. Dac nu se dorete utilizarea unui namespace, clasa trebuie referit cu tot cu namespace. n cazul de fa:
System.Text.StringBuilder sbListaNumere = new System.Text.StringBuilder(10000);

Ca dezavantaje, trebuie s menionm c la iniializarea unui StringBuilder performana scade. De asemenea, sunt foarte multe operaii care nu se pot efectua cu StringBuilder, ci cu string. Pentru concatenarea a 2 iruri nu este nevoie de StringBuilder. Se poate recomanda utilizarea acestei clase dac e nevoie de concatenarea a cel puin 4 iruri de caractere. De asemenea, pentru
13

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

creterea vitezei, trebuie s estimm lungimea final a irului (parametrul constructorului). Dac folosim constructorul vid sau lungimea estimat este mai mic dect n realitate, alocarea spaiului se face automat iar performana scade.

5. Elemente de C#
5.1. Clase pariale
n clasele corespunztoare ferestrelor, exist metode predefinite generate automat de mediul Visual Studio, care conin iniializarea controalelor grafice. Aceste metode sunt de obicei de dimensiuni mai mari i sunt separate de logica aplicaiei fiind plasate ntr-un alt fiier, numit *.Designer.cs. Definiia unei clase sau structuri sau interfee se poate mpri n dou sau mai multe fiiere surs. Fiecare fiier surs conine o parte din definiia clasei i toate prile sunt combinate cnd aplicaia este compilat. Exist cteva situaii cnd este dorit mprirea definiiei clasei:

Cnd se lucreaz la proiecte mari, mprirea clasei n fiiere separate permite mai multor programatori s lucreze la ele simultan; Cnd se lucreaz cu surse generate automat, codul poate fi adugat clasei fr s mai fie nevoie de recrearea fiierului surs. Visual Studio folosete aceast cale cnd creeaz ferestrele Windows, codul wrapper pentru servicii web s.a.m.d. Se poate crea cod care folosete aceste clase fr s mai fie nevoie de modificarea fiierului creat de Visual Studio.

Pentru a mpri definiia unei clase, se folosete cuvntul-cheie partial, dup cum este prezentat mai jos:
public partial class Employee { public void DoWork() { } } public partial class Employee { public void GoToLunch() { } }

Modificatorul partial nu este valabil n declaraiile pentru funcii delegat sau enumerri.

5.2. Proprieti. Accesori


Proprietile sunt membri care furnizeaz un mecanism flexibil de citire, scriere, sau calculare de valori ale cmpurilor private. Proprietile pot fi folosite ca i cum ar fi membri publici, dar ele sunt de fapt metode speciale numite accesori. Acestea permit ca datele s fie accesate mai uor ns n acelai timp este asigurat sigurana i flexibilitatea metodelor.

14

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

n exemplul urmtor, clasa TimePeriod reine o perioad de timp. n interiorul ei, clasa stocheaz timpul n secunde, dar exist o proprietate numit Hours care permite unui client s specifice timpul n ore. Accesorii pentru proprietatea Hours realizeaz conversia ntre ore i secunde.
class TimePeriod { private double _seconds;

} class Program { static void Main() { TimePeriod t = new TimePeriod(); // Atribuirea proprietatii Hours determina apelul accesorului "set" t.Hours = 24; // Evaluarea proprietatii Hours determina apelul accesorului "get" System.Console.WriteLine("Time in hours: " + t.Hours); } }

Poriunile get i set a unei proprieti sunt numite accesori. Implicit aceti accesori au acceai vizibilitate, sau nivel de acces cu al cmpului cruia i aparin. Totui, este folositor uneori s se restricioneze accesul la unul din accesori. De obicei, aceasta implic restricionarea accesibilitii accesorului set, n timp ce accesorul get rmne public accesibil. De exemplu:
public string Name { get { return name; } protected set { name = value; } }

n acest exmplu, o proprietate numit Name definete un accesor get i set. Accesorul get primete nivelul de accesibilitate al proprietii insi, public n acest caz, n timp ce accesorul set este restricionat n mod explicit aplicnd modificatorul de acces protected accesorului nsui.

Proprietile permit unei clase s expun o cale public de a primi (get) i aloca (set) valori, n timp ce codul de implementare sau verificare este ascuns. Accesorul get este folosit pentru a returna valoarea proprietii iar accesorul set este folosit pentru a aloca o nou valoare. Aceti accesori pot avea nivele de acces diferite. Cuvntul cheie value este folosit pentru a defini valoarea alocat de set. Proprietile ce nu implementeaz o metod set sunt doar pentru citire (read only).

15

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

public double Hours { get { return _seconds / 3600; } set { _seconds = value * 3600; } }

Proprietile au mai multe utilizri: pot valida datele nainte de a permite o modificare; pot returna datele dintr-o clas, unde datele sunt de fapt returnate din alte surse, cum ar fi o baz de date; pot produce o aciune cnd datele sunt modificate, cum ar fi ridicarea unui eveniment, sau schimbarea valorii altor cmpuri.
public class Date { private int month = 7;

//"backing store"

public int Month { get { return month; } set { if ((value > 0) && (value < 13)) { month = value; } } } }

n acest exemplu, Month este declarat ca o proprietate. n acest fel, accesorul set poate fi sigur c valoarea Month este ntre 1 i 12. Proprietatea Month folosete un cmp privat pentru a urmri valoarea actual. Locaia real a datelor proprietii este de obicei referit ca memoria auxiliar (backing store) a proprietii. Marea majoritate a proprietilor utilizeaz n mod normal cmpuri private ca memorie auxiliar. Cmpul este marcat privat cu scopul de a se asigura c poate fi accesat doar apelnd proprietatea. 5.2.1. Accesorul get Corpul accesorului get este similar cu cel al unei metode. Trebuie s returneze o valoare a tipului proprietii. Execuia accesorului get este echivalent cu citirea valorii din cmp. De exemplu, cnd se ntoarce variabila privat din accesorul get i optimizrile sunt permise, apelul ctre accesorul get este tratat inline de ctre compilator n aa fel nct nu s nu se piard timp prin efectuarea unui apel de metod. Oricum, un accesor get virtual nu poate fi tratat inline ntruct compilatorul nu tie n timpul compilrii ce metod poate fi apelat de fapt n timpul rulrii. n urmtorul exemplu, este prezentat un accesor get ce ntoarce valoarea a unui cmp privat name:

16

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Proprietile combin aspecte proprii att cmpurilor ct i metodelor. Pentru utilizatorul unui obiect, o proprietate apare ca un cmp, accesul la proprietate necesit exact aceeai sintax. Pentru realizatorul clasei, o proprietate este format din unul sau dou blocuri de cod, reprezentnd un accesor get i/sau un accesor set. Blocul de cod pentru accesorul get este executat cnd proprietatea este citit; blocul de cod pentru accesorul set este executat cnd proprietii i este alocat o nou valoare. O proprietate fr un accesor set este considerat doar pentru citire (read-only). O proprietate fr accesorul get este considerat doar pentru scriere (write-only). O proprietate cu ambii accesori este pentru citire i scriere (read-write).

Cnd se apeleaz proprietatea prin referin, n afar de cazul cnd este inta unei atribuiri, accesorul get este invocat pentru a citi valoarea proprietii. De exemplu:
Person p1 = new Person(); //... System.Console.Write(p1.Name); // se invoca accesorul get

Accesorul get trebuie s se termine cu instruciunea return sau throw, iar fluxul de control nu poate depi corpul accesorului. Schimbarea strii unui obiect utiliznd accesorul get nu este un stil bun de programare. De exemplu, urmtorul accesor produce ca efect secundar schimbarea strii obiectului de fiecare dat cnd cmpul number este accesat.
private int number; public int Number { get { return number++; } }

// Nerecomandat!

Accesorul get poate fi folosit fie ca s returneze valoarea unui cmp, fie s o calculeze i s o returneze. De exemplu:
class Employee { private string name; public string Name { get { return name != null ? name : "NA"; } } }

n segmentul de cod anterior, dac nu se atribuie o valoare proprietii Name, aceasta va ntoarce valoarea "NA" (No Account).

17

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

class Person { private string name; public string Name { get { return name; } } }

// the name field // the Name property

5.2.2. Accesorul set Accesorul set este similar cu o metod ce ntoarce void. Folosete un parametru implicit numit value (valoare), a crui tip este tipul proprietii. n exemplul urmtor, un accesor set este adaugat proprietii Name:
class Person { private string name; // campul name public string Name // proprietatea Name { get { return name; } set { name = value; } } }

Cnd se atribuie o valoare proprietii, accesorul set este invocat cu un argument ce furnizeaz noua valoare. De exemplu:
Person p1 = new Person(); p1.Name = "Joe"; // se apeleaza accesorul "set"

Folosirea parametrului implicit, value, pentru o variabil declarat local ntr-un accesor set constituie o eroare. O proprietate poate fi declarat static folosind cuvntul-cheie static. n acest fel proprietatea devine disponibil apelanilor oricnd, chiar dac nu exist nicio instan a clasei. Spre deosebire de cmpuri, proprietile nu sunt clasificate ca variabile. De aceea, nu se poate transmite o proprietate ca un parametru ref sau out. Exist instrumente care genereaz automat proprieti read-write pentru toate cmpurile. Dac ntr-o clas exist multe cmpuri, trebuie s ne ntrebm dac toate acestea trebuie s fie accesibile din exterior. Nu are sens ca toate cmpurile private ale unei clase s fie expuse n afar, chiar i prin intermediul proprietilor.

18

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

6. Aplicaii
6.1. Realizai interfaa grafic a unei aplicaii Windows pentru rezolvarea de ecuaii polinomiale de gradul I i II, precum i de ecuaii trigonometrice simple (Ecuatii.exe).

6.2. Creai clasele pentru rezolvarea celor dou tipuri de ecuaii i care vor arunca dou tipuri de excepii, conform structurii de mai jos. Fiind dou tipuri diferite de ecuaii, vom avea o interfa IEquation cu metoda Solve, din care vor fi derivate PolyEquation i TrigEquation. n clasa principal, evenimentul de tratare a apsrii butonului Calculeaza va testa tipul de ecuaie. Pentru o ecuaie polinomial: va citi coeficienii ecuaiei i va instania un obiect corespunztor:
IEquation eq = new PolyEquation(x2, x1, x0); textBoxSolutie.Text = eq.Solve();

Pentru o ecuaie trigonometric, depinznd de tipul de funcie trigonometric:


eq = new TrigEquation(TrigEquation.TrigonometricFunction.Sin, arg); textBoxSolutie.Text = eq.Solve();

Fiecare tip de ecuaie va arunca propria clas de excepie: PolyException, respectiv


TrigException.

n evenimentul butonului vom avea un singur bloc try, urmat de 3 blocuri catch: pentru cele dou tipuri de excepie, precum i pentru excepiile generice, rezultate de exemplu la ncercarea de a citi coeficienii, dac utilizatorul introduce caractere nenumerice. Excepii la rezolvarea ecuaiei polinomiale pot aprea atunci cnd toi coeficienii sunt 0 (Ecuaia are o infinitate de soluii) i cnd x2 = 0 , x1 = 0 iar x0 0 (Ecuaia nu are soluii). O excepie la rezolvarea ecuaiei trigonometrice apare atunci cnd argumentul funciilor arcsin i arccos nu aparine intervalului [-1, 1].

19

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

Indicaie: codul pentru rezolvarea ecuaiei polinomiale este prezentat mai jos, unde = x12 4 x2 x0 :
if (_x2 == 0) { _eqType = EquationType.FirstDegree; // Solutie: -_x0 / _x1 } else if (delta > 0) { double sqrtDelta = Math.Sqrt(delta); double sol1 = (-_x1 + sqrtDelta) / (2.0 * _x2); double sol2 = (-_x1 - sqrtDelta) / (2.0 * _x2); // Solutii: sol1, sol2 } else if (delta == 0) { double sol = (-_x1) / (2.0 * _x2); // Solutie: sol } else { double rsol = -_x1 / (2.0 * _x2); double isol = Math.Sqrt(-delta) / (2.0 * _x2); // Solutii: rsol isol i }

Atenie: scopul laboratorului este lucrul cu excepii, nu rezolvarea propriu-zis a ecuaiilor! 6.3. Eliminai blocurile try-catch din clasa principal a aplicaiei i efectuai tratarea excepiilor pe firul de execuie n metoda Main (EcuatiiThreadHandler.exe).
20

Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/lab_ip.htm

Florin Leon, Ingineria programarii - Laborator, http://florinleon.byethost24.com/lab_ip.htm

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