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

Wednesday, December 23, 2015


Često pitanje u OOP načinu programiranju jeste koja je zapravo razlika između strukture i klase. Tema ovog blog posta će biti objašnjenje, prave razlike između strukture i klase u programskom jeziku C#. Ovo pitanje je jako aktuleno jer ako bolje pogledamo strukturu i klasu, one su skoro identične, imaju atribute, funkcije članice, konstruktor, destruktor ...

Prvo ću krenuti sa strukturom, struktura u C# programskom jeziku je value type što znači da njena alokacija se uvijek 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 primjeni 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. Ako se vodimo predhodno naučenim pojmom spremanja strukture na stek, 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 vrijeme 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 zauzetu memorije na steku i još jedna bitna stvar je da u funkciji mi radimo sa kopijom objekta koji je poslan pri pozivu funkcije i svaku promjenu 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 primjer primjenimo na klase koje su reference type, iz jednog mini testa koji ćemo uraditi u slijedećim koracima...dolazimo do zaključka da se klase uvijek š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 proslijedimo adresu (referencu) mi u funkciji direktno pristupamo toj memorijskoj lokaciji i radimo potrebne izmjene nad našim objektom.

Malo objašnjenje za predhodne pojmove u slučaju da nisu jasne stvari oko adresa. Svaki vaš objekat koji je smješ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 slijedećem primjeru:

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 riječima class i struct. Ali naravno velika je razlika u pozadini, a to ćemo upravo dokazati na slijedeći način:

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



A u main funkciji imamo slijedeću situaciju:


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


Ako pažljivo pratimo ispis na konzoli, možemo primjetiti da se vrijednost atributa naše strukture promjeni samo u funkciji PromjenaStanjaStrukture(), kada se završila funkcija u mainu imamo informaciju da je vrijednost atributa strukture ista kao i prije poziva. Iz ovoga možemo zaključiti samo jedno, da je naša struktura po svojoj prirodi poslana u funkciju po vrijednosti i da smo u funkciji radili i vršili promjene 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 vrijednosti (7, 12), te u funkciji PromjenaStanjaKlase(), kao što je i definisano dobija vrijednosti (20, 7), poslije završetka slijedi ispis koji nam ispisuje one vrijednosti koje je klasa dobila u funkciji. Objašnjenje ovoga je da se klase uvijek šalju po referenci, a ne po vrijednosti kao što to strukture rade. Funkcija PromjenaStanjaKlase() dobila je adresu naše klase i mogla je direktno da utiče na promjenu njenih atributa tj. modifikovali smo originalni objekat.

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

Nadam se da vam je ovaj blog post bio od pomoći i da ste nešto novo naučili, preporučujem vam da pogledate i ostale postove na blogu koji se bave sličnim temama. Do slijedećeg posta ...

Pozdrav! Almir Vuk | AV Development

You Might Also Like

0 comments