struct - C#

struct - C#

Avtor: Aleš Brelih

Kaj je struct?

Structi so eni izmed osnovnih podatkovnih tipov v C#. S structi je imel opravka vsak, ki je programiral v jeziku C#, saj se osnovni podatkovni tipi (npr. int, bool, char, double) štejejo med structe.
Torej kaj je struct? Struct je struktura, ki je zelo podobna razredom. V takšni obliki, kot jih bom predstavil obstajajo samo v programskem jeziku C# (čeprav je Java zelo podoben programski jezik, imajo structi v javi popolnoma drugačen pomen). Torej struct je podatkovna struktura, v kateri so zapisane lastnosti objekta. V njem pa so lahko zapisane tudi metode, s katerimi upravljamo z objektom. Vse skupaj pa namiguje, da imamo spet opravka z razredi.

Prvi struct

Structi so zelo preprosti za uporabo, saj si jih lahko predstavljamo kok nekakšen preprostejši nadomestek za razrede. Čeprav se razredi in objekti razlikujejo v tipu podatkov, pa se ustvarjanje structov ne razlikuje veliko od ustvarjanja razredov.


struct (opis točke)

public struct structTocka
    {
        public int xKoord { get; set; }
        public int yKoord { get; set; }
        public override string ToString()
        {
            return xKoord+"-"+yKoord;
        }
    }
 

razred (opis točke)

public class classTocka
    {
        public int xKoord { get; set; }
        public int yKoord { get; set; }
        public override string ToString()
        {
            return xKoord+"-"+yKoord;
        }
    }


Ustvarjanje structa in razreda (Film). Klikni

Kako ustvariti struct

Prvi struct

Razlik pri ustvarjanju structa in razreda v tem primeru ni. Vendar kljub vsemu moramo paziti na dve ključni razliki:

  • Lastnosti ne smejo imeti privzetih vrednosti!
  • V structu ne smemo uporabiti konstruktorja brez parametrov!


(napakeKonstruktor.jpg)
Napake v konstruktorju

Upravljanje z pomnilnikom

Za boljše razumevanje naslednjih razdelkov si najprej poglejmo kako se v pomnilnik shranijo različni podatki v programu. Za pravilno delovanje programa .NET orodje uporablja dve različni mesti v pomnilniku. To sta ti. kopica (angl. heap) in sklad (angl. stack). V pomnilniku pa najdemo tudi kazalce (angl. pointers), ki nam kažejo na naslov objekta, ki se bo naslednji izvedel.

(stack_heap.jpg)
-Prikaz- sklada in kopice

Sklad (angl. stack)

Sklad je programska struktura, ki deluje po načelu LIFO (Last in first out). Sklad si lahko predstavljamo kot več škatel, ki jih polagamo eno na drugo. Škatlo dodamo vedno, ko pokličemo novo metodo. Uporabljamo pa lahko samo škatlo, ki se nahaja na vrhu (torej vrh sklada). Ko se metoda zaključi in zadnje škatle ne potrebujemo več, jo preprosto odstranimo in skočimo v naslednjo škatlo, ki bo na vrhu. Vrh sklada nam lahko pomaga pri iskanju mesta, kje v kodi se trenutno nahajamo.


(stack_que.jpg)
Način delovanja sklada, Vir:

Kopica (angl. heap)

Kopica pa služi kot samo prostor za zapis podatkov. Ker pri kopici vrstni red zapisa podatkov ni pomemben, lahko do vseh podatkov vedno dostopamo (torej nismo omejeni samo na zadnje podatke). Torej si lahko kopico predstavljamo kot različne predmete razporejene na mizi. Ko enega izmed njih potrebujemo, ga preprosto vzamemo.

Čiščenje podatkov

Ker pomnilnika ni neomejeno, moramo tudi poskrbeti za čiščenje pomnilnika. Sklada ni potrebno čistiti, saj se podatki odstranijo, ko jih ne potrebujemo več. Tukaj pa se zadeva za kopico zakomplicira, saj podatki vedno ostanejo v pomnilniku. Zato za optimalno delovanje programov potrebujemo Zbiralca smeti (angl. Garbage collection - GC). Zbiralec smeti lahko sami zaženemo na naključnem mestu v naši kodi. Vendar to ni potrebno, saj se bo sam izvedel, ko se bo del pomnilnika zapolnil s podatki. Zbiralec smeti odstrani vse objekte v kopici, ki jih ne potrebujemo več. Takrat pa mora tudi spremeniti vse reference v kopici in skladu. Ker je ta postopek eden izmed zahtevnejši pri delovanju programa, moramo paziti kaj shranjujemo v kopico in kaj v sklad, saj s tem lahko zelo pohitrimo delovanje programov.

Kam se podatki shranijo

Za referenčne tipe podatkov je preprosto. Vse shranimo v kopici. Za podatkovne tipe pa se stvari malo zakomplicirajo, saj ni točno določeno kam se morajo shraniti. Odvisno je od tega kje so deklarirani. Če podatkovni tip deklariramo v razredu se bo skupaj z objektom shranil v kopici. V primeru, da ga uporabimo v metodi pa se shrani v sklad

Razlika med razredi in structi

Čeprav sta si strukturi zelo podobni pa lahko med njimi najdemo veliko razlik.

  • Razredi so lahko null. Structi pa ne.

  • Ker se structi in razredi razlikujejo v tipu podatkov, se tudi shranijo na različna mesta v pomnilniku. Structi se lahko shranijo na obe mesti, saj so podatkovni tip in njihovo mesto bo določeno od tega, kje smo struct deklarirali. Objekti razredov pa se shranijo na kopico, saj spadajo med referenčne tipe podatkov.

  • Druga razlika med razredi in structi pa je tudi povezana z lokacijo, kje se določene strukture shranijo. Structi nimajo destruktorjev, saj se stack prazni sam, ko določenega podatka ne potrebuje več. V razredih pa obstajajo destruktorji, saj moramo v heap-u odstraniti vse objekte, ki jih ne potrebujemo več. S tem se delovanje programa izboljša (optimizacija).

  • Verjetno najpomembnejša razlika med razredi in structi pa je v tem, da pri ustvarjanju structov ne moremo uporabiti dedovanja. To pa je tudi razlog, zakaj se večkrat izognemo uporabi structov.

Katerega izbrati?

Pri uporabi podatkovnega tipa se zmanjša velikost kopice. To pomeni, da Odstranjevalec smeti ne imel tako pogostih ciklov in s tem se bo tudi izboljšalo delovanje programa. Toda to še ne pomeni, da je uporaba podatkovnih tipov zmeraj boljša. Saj premikanje velikega podatkovnega tipa seveda potrebuje več časa kot pa premikanje reference na določen objekt.



Torej kdaj je bolje uporabiti struct namesto razreda?

  • Objekt bo načeloma preprost. Vseboval bo malo podatkov (Microsoft priporoča, da je največja velikost structa le 16 bitov).

  • Objekt uporabimo samo v zanki in ga nato ne potrebujemo več.

  • Objekt ne potrebujemo po celotni kodi.

  • Objekt ne bo izhajal iz že obstoječega objekta (dedovanje) in objekta ne bomo potrebovali več

  • Uporaba boxinga in unboxinga.

  • Objekta ne premikamo.

Pakiranje in odpakiranje

Pakiranje je eden izmed najpomembnejših pojmov v C#. Z njim lahko povežemo podatkovne in referenčne tipe, tako da spremenimo podatkovne tipe spremenimo v referenčne in obratno. Torej naj omogoča obravnavo podatkovnega tipa kot objektni tip. Pakiranje pa lahko tudi uporabimo, ko želimo povezati več različnih objektov kot enega. Ta način programiranja obstaja, ker v .NET okolju tudi vsak podatkovni tip deduje iz System.Object.


testiranje pakiranja:

static void Main(string[] args)
        {
            int stevilo = 1;
            string beseda = "ena";
            char znak = 'e';
            testcl novObj = new testcl(); //naključen objekt, ToString vrne niz "objekt"
            object[] sezObjektov = {(object) stevilo,(object)beseda,(object)znak,(object)novObj}; && objekte zapakiramo
            Console.WriteLine("Izpiši podatkovne tipe objektov: ");
            foreach (var obj in sezObjektov) //ker so objekti pakirani lahko uporabimo samo eno zanko
            {
                Console.WriteLine("Tip objekta: " + obj.GetType() + ". Vrednost: " + obj.ToString());
            }
            Console.ReadLine();
        }

rezultat:


(testBox.jpg)
Delovanje testnega programa

Viri

0%
0%