Programování

Hluboký ponor: Hodnotové a referenční typy v .Net

Typy v Microsoft .Net mohou být buď hodnotový typ, nebo referenční typ. Zatímco typy hodnot jsou obecně uloženy v zásobníku, referenční typy jsou uloženy ve spravované haldě.

Typ hodnoty je odvozen od System.ValueType a obsahuje data uvnitř jeho vlastní alokace paměti. Jinými slovy, proměnné nebo objekty nebo typy hodnot mají svoji vlastní kopii dat.

Mezitím typ odkazu rozšiřuje System.Object a ukazuje na umístění v paměti, které obsahuje skutečná data. Můžete si představit referenční typ podobný ukazateli, který je implicitně dereferencován, když k nim přistupujete. Integrované typy odkazů podporované C # zahrnují: objekt, řetězec a dynamický. Všechny základní datové typy, Boolean, Date, struktury a výčty jsou příklady typů hodnot. Mezi příklady typů odkazů patří: řetězce, pole, objekty tříd atd. Chcete-li vytvořit typy odkazů v C #, můžete využít výhod těchto klíčových slov: class, interface and delegate.

Všimněte si, že na rozdíl od referenčního typu nemůžete odvodit od typu hodnoty, ani přiřadit hodnotu null přímo typu hodnoty. Hodnotu null můžete přiřadit k typu hodnoty pouze využitím výhod typů s možnou hodnotou null - funkce přidané k novějším verzím .Net Framework. Když se typ hodnoty zkopíruje do jiného, ​​hodnota se zkopíruje. S hodnotami v nich tedy můžete manipulovat nezávisle na druhém - změna v jednom neovlivní druhého. Naopak při kopírování typu odkazu do jiného se odkaz zkopíruje. Pokud změníte jeden z nich, ovlivní se i druhý. Jako příklad, pokud je jeden z odkazů nastaven na null, druhý se také stane null.

Úložiště

CLR ukládá objekty do tří typů umístění úložiště - registry, zásobník nebo spravovaná halda. Zatímco objekty s krátkou životností jsou uloženy uvnitř registrů nebo zásobníku, objekty s dlouhou životností jsou uloženy v haldě. Jak jsem již zmínil dříve, typy hodnot jsou obecně uloženy v zásobníku.

Je běžnou mylnou představou, že typy hodnot jsou vždy uloženy v zásobníku. Raději bych řekl, že hodnotové typy umět být uloženy v zásobníku, když je proměnná buď dočasná proměnná, nebo je to lokální proměnná a kompilátor JIT se rozhodne hodnotu nezapsat. Skutečné umístění hodnotového typu v podstatě závisí na implementaci kompilátoru JIT. Všimněte si, že typ hodnoty lze uložit do rámce zásobníku, do registru CPU nebo dokonce do paměti haldy, pokud je typ hodnoty obsažen uvnitř objektu, tj. Pokud je součástí referenčního typu. Naopak, referenční typy jsou uloženy v haldě GC. Odkaz je uložen v zásobníku, zatímco objekt je přidělen v haldě.

Instance nebo odkazy typu hodnoty jsou uloženy v zásobníku, registru nebo v haldě v závislosti na tom, zda je doba života instance nebo reference krátkodobá nebo dlouhá. Typ hodnoty se může na zásobníku nacházet, pokud se jedná o místní proměnné, a ve spravované haldě, pokud jde o pole třídy, tj. Patří k referenčnímu typu nebo jsou jeho součástí.

Předávání hodnotou a předávání odkazem

Následující výpis kódu ukazuje, jak můžete předat proměnnou metodě podle hodnoty.

 statický void přírůstek (int i)

        {

i = i + 1;

        }

static void Main ()

        {

int x = 1;

Přírůstek (x);

Console.WriteLine ("Hodnota x je:" + x);

Console.Read ();

        }

Všimněte si, že můžete předat typ hodnoty jako odkaz na metodu pomocí ref klíčového slova. Následující příklad kódu to ilustruje.

statický void přírůstek (ref int i)

        {

i = i + 1;

        }

static void Main ()

        {

int x = 1;

Přírůstek (ref x);

Console.WriteLine ("Hodnota x je:" + x);

Console.Read ();

        }

Po provedení výše uvedeného kódu se v konzole zobrazí zpráva „The value of x is: 2“.

Box a rozbalení

Převod typu hodnoty na referenční typ se označuje jako box. Unboxing je pravý opak - je definován jako proces převodu referenčního typu na typ hodnoty. Následující fragment kódu ilustruje box a unboxing v C #.

int i = 100;

Objekt obj = i; //Box

i = (int) obj; //Rozbalení