Dubinsko ronjenje: Vrijednosti i referentni tipovi u .Netu

Tipovi u Microsoftu .Net mogu biti ili vrijednosni ili referentni. Dok su tipovi vrijednosti općenito pohranjeni u stogu, referentni tipovi pohranjeni su u upravljanoj hrpi.

Tip vrijednosti potječe od System.ValueType i sadrži podatke unutar vlastite alokacije memorije. Drugim riječima, varijable ili objekti ili vrste vrijednosti imaju vlastitu kopiju podataka.

U međuvremenu, referentni tip proširuje System.Object i pokazuje na mjesto u memoriji koje sadrži stvarne podatke. Možete zamisliti referentni tip sličan pokazivaču koji se implicitno preusmjerava kad im pristupate. Ugrađene referentne vrste koje podržava C # uključuju: objekt, niz i dinamičke. Svi temeljni tipovi podataka, logički podaci, datum, strukture i nabrajanja primjeri su tipova vrijednosti. Primjeri referentnih tipova uključuju: nizove, nizove, objekte klasa itd. Da biste stvorili referentne tipove u C #, možete iskoristiti ove ključne riječi: klasa, sučelje i delegat.

Imajte na umu da za razliku od referentne vrste, ne možete izvesti iz vrste vrijednosti niti možete dodijeliti null vrijednost izravno vrsti vrijednosti. Nulskoj vrijednosti možete dodijeliti vrstu vrijednosti samo iskorištavanjem poništenih tipova - značajke dodane novijim verzijama .Net Framework-a. Kada se vrsta vrijednosti kopira u drugu, vrijednost se kopira. Dakle, možete manipulirati vrijednostima u njima neovisno o drugoj - promjena jedne ne utječe na drugu. Naprotiv, kada kopirate vrstu reference u drugu, referenca se kopira. Ako promijenite jedno od njih, to utječe i na drugo. Kao primjer, ako je jedna referenca postavljena na nulu, druga također postaje nula.

Mjesta skladištenja

CLR pohranjuje objekte na tri vrste mjesta za pohranu - registri, stog ili upravljana hrpa. Dok su kratkotrajni objekti pohranjeni u registre ili stog, dugovječni se objekti pohranjuju u hrpu. Kao što sam već spomenuo, vrste vrijednosti obično se pohranjuju u stog.

Uobičajena je zabluda da su vrste vrijednosti uvijek pohranjene u stogu. Prije bih rekao da se tipovi vrijednosti mogu pohraniti u stog kada je varijabla ili privremena varijabla ili je lokalna varijabla, a JIT kompajler odluči ne registrirati vrijednost. U osnovi, stvarno mjesto tipa vrijednosti ovisi o implementaciji JIT prevoditelja. Imajte na umu da se vrsta vrijednosti može pohraniti u okvir steka, u CPU registar ili čak u memoriju hrpe ako je vrsta vrijednosti sadržana unutar objekta, tj. Ako je dio referentnog tipa. Naprotiv, referentni tipovi pohranjeni su u GC hrpi. Referenca se sprema u stog dok je objekt dodijeljen u hrpi.

Primjerci ili reference vrste vrijednosti pohranjuju se u stog, registar ili u hrpu, ovisno o tome je li životni vijek instance ili reference kratkotrajan ili dugo traje. Vrsta vrijednosti može se nalaziti u stogu ako su lokalne varijable, a u upravljanoj hrpi ako su polja klase, tj. Pripadaju ili su dio referentnog tipa.

Prolazeći pored vrijednosti i prolazeći pored reference

Sljedeći popis kodova prikazuje kako možete proslijediti varijablu metodi po vrijednosti.

 static void Increment(int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

Imajte na umu da vrstu vrijednosti možete proslijediti kao referencu na metodu pomoću ključne riječi ref. Sljedeći popis kodova to ilustrira.

static void Increment(ref int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(ref x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

Kada se izvrši gornji kôd, na konzoli će se prikazati poruka "Vrijednost x je: 2".

Boks i raspakiranje

Pretvorba vrste vrijednosti u referentnu vrstu poznata je kao boks. Raspakiranje je upravo suprotno - definirano je kao postupak pretvorbe referentnog tipa u tip vrijednosti. Sljedeći isječak koda ilustrira boks i raspakiranje u C #.

int i = 100;

Object obj = i; //Boxing

i = (int) obj; //Unboxing