Enumeracije ili nabrajanje tipa Enum u C# programskom jeziku


Enumerations - enumeracije su specijalni vrednosni tipovi podataka koji omogućava da zadate grupu imenovanih numeričkih konstanti. U Srbiji se enumeracija često naziva nabrajanje, ali onda je bolje da kažete nabrajanje tipa enum jer postoje i druge vrste nabrajanja u C# programskom jeziku.

Kada hoćete da deklarišete enumeraciju u C# programskom jeziku; koristite ključnu reč enum izvan funkcija kao što to radite sa strukturama.
enum  ime_enumeracije
{
vrednost1;     vrednost2;     … }

Jednom kad ste deklarisali enumeraciju, možete da je koristite na tačno isti način kao i bilo koji drugi numerički tip podataka. Vrednostima enumeracije možete dodeljivati jedino celobrojnu vrednost. Ukoliko želite vrednostima enumeracije da dodeljujete vrednosti tipa stringova, onda bolje razmislite o tome da koristite strukturu u kojoj će nabrajanje biti jedan od članova strukture.

Kako se dodeljuju vrednosti strukturi enumeracija?
Jednostavno, ako vrednostima niste dodelili nikakvu celobrojnu vrednost, onda se podrazumeva da nabrajanje počinje od 0 kao i u nizovima.
enum  ime_enumeracije
{
vrednost1 = 0;     vrednost2 = 1;     … }

Međutim ukoliko vi dodate neku vašu celobrojnu vrednost, posle nje će svaka vrednosti biti uvećana za 1. Npr.

enum  ime_enumeracije
{
vrednost1 = 1;     vrednost2;     … }
To znači da je u ovom slučaju vrednost2 jednaka 2, sledeća vrednost bi imala vrednost 3 itd. Vi možete imati iste vrednosti u stavkama enumeracije ali ne vidim poentu zašto bi ste to radili. Enumeracije su po defaultu tipa integer ali vi možete to promeniti u drugi celobrojni tip podataka.
enum ime_enumeracije : byte { ... }

Strukture u C# programskom jeziku


Struktura se deklariše kao i enumeracija ili klasa, samo što koristi ključnu reč struct. Sintaksa strukture je:

Struct ime_strukture 
{
       članovi_strukture;
};

Članovi strukture mogu imati pored promenjivih i metode i čak konstruktore. Strukture jesu izvedene iz klase Object, ali one ne mogu da vrše nasleđivanje. To u prevodu znači da struktura ne može da sadrži druge strukture ili klase. Vi ne možete imati konstruktor u strukturi koji ne uzima ni jedan parametar. On već postoji i implicitno inicijalizuje na nulu sva polja u strukturi. Struktura ne može da sadrži destruktor. Vi ne morate da koristite ključnu reč new da instacirate članove strukture ali nije zabranjeno. To takođe ne znači da ćete sa ključnom rečju new prebaciti deo memorije strukture sa steka na hip. Struktura se isključivo formira u stek segmentu.


*** Za one koji žele da znaju malo više: ***

Struktura jeste slična klasi ali nije klasa, koristi se slično enumeracijama ali nije enumeracija jer nema nabrajanja. Najjednostavnije rečeno, struktura vam je vrednosni tip podataka koji služi da enkapsulirate manji skup podataka. Za razliku od klasa koji su referentni tip i koji se kreiraju na hipu, strukture se kreiraju na steku i sve dok je struktura mala, upravljanje memorijom koja upravlja hipom je znatno smanjeno. Možete se pitati zašto je to bitno, zar sad treba da razmišljate i o memoriji dok programirate. U principu uvek treba u programiranju da razmišljate o memoriji bez obzira koliko je imate u računaru. Da bi vam bilo jasnije, treba da znate da je memorija računara definisana u tri segmenta. U tekst ili kod segment, stek segment i hip segment.


( Strukture su vrednosni tip podataka )
 
Kad npr. otvorite *.exe datoteku, sav taj mašinski, ljudski nečitljiv kod se stavlja u tekst segment ili kako ga češće zovu kod segment memorije. Stek segment se uglavnom koristi za čuvanje privremenih podataka, često u obliku promenjivih i automatskih metoda, dok se hip segment više koristi za različite svrhe programa s obzirom da se bavi dinamičkom raspodelom memorije. U hip segmentu memorije, obrazac raspodele memorije nije poznat tokom izvršavanja memorije. Ono što je najbitnije da upamtite je da se stek segment brže izvršava od hip segmenta ali je zato stek segment memorije manji i skuplji.


Razlika između Struct i Class u C# programskom jeziku

Često pitanje u OOP načinu programiranju jeste koja je zapravo razlika između strukture i klase.

Prvo ću krenuti sa strukturom, struktura u C# programskom jeziku je value type što znači da se njena alokacija se uvek nalazi na steku (stack).
Klasa za razliku od strukture svoju alokaciju ima na heap-u tj. u dinamičkoj dijelu memorije, u potpuno drugom logičkom djelu memorije u odnosu na stek.

U primeni, strukturu ćemo najčešće naći kada radimo sa manjim tipovima podataka i manjim količinama podataka, glavni razlog ove "odluke" jeste taj što ona uveliko utiče na performanse naše App (aplikacije). Ako se vodimo predhodno naučenim pojmom čuvanja strukture na steku, imamo pojavu da kada želimo poslati strukturu u neku od funkcija, mi zapravo tada šaljemo čitavu strukturu i njen sadržaj. Iz ovog možemo zaključiti da u runtime-u imamo proces kompletnog kopiranja objekta onoliko puta koliko pozivamo funkcija koje kao parametar preuzimaju našu strukturu, računica i zaključak je jednostavan: u slučaju veće strukture imamo mnogo veće vreme izvršavanja koje uglavnom ide na kopiranje svih informacije iz strukture u njenu lokalnu kopiju.

Važno za napomenuti je da je stek mnogo manja logička količina memorija u odnosu na heap, i proces slanja strukture kroz funkcije duplo povećava zauzeće memorije na steku. Još jedna bitna stvar je da u funkciji mi radimo sa kopijom objekta koji je poslat pri pozivu funkcije i svaku promenu koju želimo raditi moramo na adekvatan način uraditi i na "glavnom" objektu.

Kada uzmemo u obzir čitav proces kopiranja shvatimo koliko je ovo "skupo" za našu App... Ako ovaj isti primer primenimo na klase koje su reference type, iz jednog mini testa koji ćemo uraditi u sledećim koracima...dolazimo do zaključka da se klase uvek šalju po referenci tj. u funkciju koja prima našu klasu mi šaljemo adresu našeg objekta u dinamičkoj memoriji i samim tim mi nemamo potrebu za kopiranjem onoga što se nalazi u klasi, a sa ugla performansi šaljemo mnogo manju informaciju (za razliku do strukture i slanja čitavog objekta). Kada prosledimo adresu (referencu) mi u funkciji direktno pristupamo toj memorijskoj lokaciji i radimo potrebne izmene nad našim objektom.

Malo objašnjenje za predhodne pojmove u slučaju da nisu jasne stvari oko adresa. Svaki vaš objekat koji je smešten u memoriji ima svoju memorijsku adresu tj. lokaciju na kojoj se nalazi. Kada vi imate informaciju tj. adresu na kojoj je vaš objekat vi imate "pravo" i mogućnost da ga direktno editujete... mnogo će biti jasnije u sledećem primeru:

Na slikama ispod vidite kako izgleda naša struktura pod imenom "TackaKoordinateStruktura", njeni atributi i konstruktor:


kao i kod na kojem je definisana naša klasa "TackaKoordinateKlasa", atributi i konstruktor:


Kao što i vidite skoro da su identične, jedina razlika na prvi pogled je u ključnim rečima class i struct. Ali naravno velika je razlika u pozadini, a to ćemo upravo dokazati na sledeći način:

Za potrebu ovoga mini testa koristit ćemo dve funkcije koje kao parametar primaju strukturu i klasu, naravno jedna prima strukturu, a druga klasu i izgledaju ovako;


A u main funkciji imamo sledeću situaciju:


Ako pokrenemo naš program možemo očekivati sledeći ispis na konzoli:


Ako pažljivo pratimo ispis na konzoli, možemo primetiti da se vrednost atributa naše strukture promeni samo u funkciji PromjenaStanjaStrukture(), kada se završila funkcija u mainu imamo informaciju da je vrednost atributa strukture ista kao i pre poziva. Iz ovoga možemo zaključiti samo jedno, da je naša struktura po svojoj prirodi poslata u funkciju po vrednosti i da smo u funkciji radili i vršili promene sa njenom kopijom koja je naravno uništena pri završetku funkcije (silazak sa steka).

Sa druge strane ako posmatramo ponašanje naše klase, pri inicijalizaciji je dobila vrednosti (7, 12), te u funkciji PromjenaStanjaKlase(), kao što je i definisano dobija vrednosti (20, 7), posle završetka sledi ispis koji nam ispisuje one vrednosti koje je klasa dobila u funkciji. Objašnjenje ovoga je da se klase uvek šalju po referenci, a ne po vrednosti kao što to strukture rade. Funkcija PromjenaStanjaKlase() dobila je adresu naše klase i mogla je direktno da utiče na promenu njenih atributa tj. modifikovali smo originalni objekat.

Iz ovog mini testa i primera dokazali smo i zaključili da se strukture uvijek šalju po vrednosti, a klase po referenci i ovo nam ujedno i govori pravu razliku između strukture i klase u C# programskom jeziku.

Last modified: Monday, 23 September 2019, 11:14 PM