недеља, 13. децембар 2015.

Vrednosni i referentni tipovi podataka u C# programskom jeziku


Iz onog što ste do sada čitali na postovima mog bloka o C# programskom jeziku , vi već sad možete predvideti koliko se ovaj programski jezik razlikuje od drugih programskih jezika i koliko međujezik IL – Intermediate Language ima ključnu ulogu u okruženju .Net Framework-a. Glavna osobina IL jeste upravo veoma precizno razlikovanje vrednosni i referentni tipova podataka. Zato i vi kao programer morate da razlikujete vrednosni i referentni tip podataka i da tačno znate kad koji treba koristiti. Takođe, trebate uvek biti svesni da C# kompajler kompajlira jedino kontrolisani kod i da IL vrši strogo tipiziranje podataka, upravlja greškama putem izuzetaka, koristi atribute i apsolutno je okrenut objektno orijentisanosti i korišćenju raznih tipova klasa i interfejsa. Osnovna razlika između vrednosnog i referentnog tipa je sam način kako se ovim tipovima pristupa.




( Vrednosni i referentni tipovi podataka u C# programskom jeziku )


Value types – vredosni tipovi su tipovi koji svoju vrednost direktno čuvaju u memoriji. U C++ programskom jeziku, takve tipove zovu jednostavni tipovi podataka. Vrednosni tipovi podataka se uvek čuvaju na steku. Kad izađu iz zone delovanja, skroz se brišu i oslobađaju memoriju. Oni imaju fiksiranu veličinu i kad ih deklarišete, vi u stvari vršite alokaciju bloka memorije dovoljno velikog da čuva odgovarajuću vrednost. Kad vršite kopiranje vrednosnog tipa pravi se nova promenjiva i zato se promene kod originala i obratno ne odražavaju. Vrednosni tipovi podataka su:

Predefinisani celobrojni tipovi podataka
  • byte – System.Byte
  • sbyte – System.SByte
  • short – System.Int16
  • ushort – System.UInt16
  • int – System.Int32
  • uint – System.UInt32
  • long – System.Int64
  • ulong – System.UInt64
Predefinisani tipovi podataka sa pokretnim zarezom
  • float – System.Single (32bit)
  • double – System.Double (64bit)
  • decimal – System.Decimal (128bit)
Predefinisani boolean i char vrednosni tipovi
  • bool – System.Boolean
  • char – System.Char
Nepredefinisani vrednosni tipovi
  • Struct – Struktura
  • Enum – Enumerator
Reference types – referentni tipovi su tipovi koji čuvaju samo adresu ili referencu na vrednost. Kada pravite referentni tip, vi u stvari odvajate samo mali deo memorije koji čuva adresu drugog bloka memorije u managed heap – kontrolisanom hipu. Preciznije, referentni tip se nalazi na dve memorijske lokacije. Pravi podaci su na hipu dok promenjiva koja sadrži pokazivač na taj objekat se nalazi na steku. Kad ta promenjiva izađe iz zone delovanja, referenca objekta se briše ali ne i sam objekat. Ukoliko postoje druge reference na isti objekat, objekat ostaje nedirnut. Da, vi možete imati više referenci na isti objekat, ali najvažnije je da shvatite kad se vrednost promeni na objektu, promeniće se i na svim referencama. Referenti tipovi podataka su:
  • string – System.String
  • object – System.Object
ali i:
  • Class – klasa
  • Array – niz
  • Interface – interfejs
  • Delegate – delegat
Da li su referentni tipovi pokazivači?

To je diskutabilno pitanje. Programeri C i C++ programskog jezika imaju veliku naviku da koriste pokazivače, ali od pojave C# programskog jezika ste oslobođeni od pokazivača. Mnogi studenti i programeri su srećniji zbog toga. Za referentni tip ne možete reći da su pokazivači iako oni na nivou kompajlera jesu pokazivači; ali se referentni tip više možete definisati kao zamena za pokazivače, stime da imaju ograničenja. Referentni tip mora uvek da pokazuje na objekat dok pokazivač ne mora. Na primer kod inkrementacije, pokazivač pristupa direktno adresi pokazivača dok referenca samo na vrednost. Pokazivač se može preusmeriti dok je referentni tip stalno vezan za objekat. Referentni tip radi direktno sa objektom dok pokazivač radi indirektno preko adrese objekta itd.

Da li je statička klasa vrednosni tip?

Nije. Svaka klasa je referentni tip bez obzira kako je korisnik definiše.

Šta je Nullable tip podataka?

Nullable tip podataka je u stvari instanca System.Nullable<T> structure. Struktura ima Value i HasValue svojstva. Svojstvo HasValue je tipa bool i koristi se da proveri da li promenjiva sadrži null vrednost. Nullable tipovi podataka se uglavnom koriste za inicijalizaciju referentnih tipova podataka, ali se najviše koriste kada radite sa bazama podataka i sa drugim vrstama podataka koji sadrže elemente kod kojih ne možete da dodelite vrednost. Kad nekom objektu dodelite vrednost null onda taj objekat nije inicijalizovan.

object referenceType = null;

Međutim, null vrednost se ne može dodeliti vrednosnim tipovima. Ovo će izazvati grešku.

int valueType = null; // Error

Da bi ste vredonosnog tipu podatka dodelili nullable vrednost, koristite modifikator ?  

int? valueType = null;

Praktičan primer razlike vrednosnog i referentnog tipa

Pogledajte kod koji koristi strukturu kao vrednosni tip i klasu kao referentni tip. Kada promenite vrednost na koju referentni tip referencira, automatski će se i sve reference promeniti, dok to nije slučaj kod vrednosni tipova.

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ValueAndReferenceTypes
{
    struct ValueType
    {
        public string FirstName;
        public string LastName;
        public string BlogAddress;

    }

    class ReferenceType
    {
        public string FirstName;
        public string LastName;
        public string BlogAddress;

    }

    class Program
    {
        static void Main(string[] args)
        {
            bool correct = false;
            string firstName, lastName, blogAddress;

            ReferenceType MyReferenceType = new ReferenceType();
           
            do
            {
                Write("Your first name: ");
                firstName = ReadLine();

            } while (correct = String.IsNullOrWhiteSpace(firstName));

            do
            {
                Write("Your last name: ");
                lastName = ReadLine();

            } while (correct = String.IsNullOrWhiteSpace(lastName));

            do
            {
                Write("Your blog address: ");
                blogAddress = ReadLine();

            } while (correct = String.IsNullOrWhiteSpace(lastName));

            ValueType MyValueType1 = new ValueType();
            MyValueType1.FirstName = firstName;
            MyValueType1.LastName = lastName;
            MyValueType1.BlogAddress = blogAddress;

            ReferenceType MyReferenceType1 = new ReferenceType();
            MyReferenceType1.FirstName = firstName;
            MyReferenceType1.LastName = lastName;
            MyReferenceType1.BlogAddress = blogAddress;


            WriteLine(Environment.NewLine + "MyValueType1: " +
                      Environment.NewLine + MyValueType1.FirstName + " " + MyValueType1.LastName + " " +
                      Environment.NewLine + MyValueType1.BlogAddress);

            ValueType MyValueType2 = MyValueType1;

            WriteLine(Environment.NewLine + "MyValueType2: " +
                      Environment.NewLine + MyValueType2.FirstName + " " + MyValueType2.LastName + " " +
                      Environment.NewLine + MyValueType2.BlogAddress);

            MyValueType1.FirstName = "Bill";
            MyValueType1.LastName = "Gates";
            MyValueType1.BlogAddress = "www.gatesnotes.com";

            WriteLine(Environment.NewLine + "MyValueType2 after changed ValueType1: " +
                      Environment.NewLine + MyValueType2.FirstName + " " + MyValueType2.LastName + " " +
                      Environment.NewLine + MyValueType2.BlogAddress);

            WriteLine(Environment.NewLine + "--------------------");

            WriteLine(Environment.NewLine + "MyReferenceType1: " +
                      Environment.NewLine + MyReferenceType1.FirstName + " " + MyReferenceType1.LastName + " " +
                      Environment.NewLine + MyReferenceType1.BlogAddress);

            ReferenceType MyReferenceType2 = MyReferenceType1;

            WriteLine(Environment.NewLine + "MyReferenceType2: " +
                      Environment.NewLine + MyReferenceType2.FirstName + " " + MyReferenceType1.LastName + " " +
                      Environment.NewLine + MyReferenceType2.BlogAddress);

            MyReferenceType1.FirstName = "Bill";
            MyReferenceType1.LastName = "Gates";
            MyReferenceType1.BlogAddress = "www.gatesnotes.com";

            WriteLine(Environment.NewLine + "MyReferenceType2 after changed MyReference1: " +
                      Environment.NewLine + MyReferenceType2.FirstName + " " + MyReferenceType1.LastName + " " +
                      Environment.NewLine + MyReferenceType2.BlogAddress);

            ReadKey();

        }
    }
}

Kad pokrenete program, rezultat će pokazati razliku između vrednosnog i referentnog tipa.

Your first name: Manuel
Your last name: Radovanovic
Your blog address: www.manuelradovanovic.com

MyValueType1:
Manuel
Radovanovic
www.manuelradovanovic.com

MyValueType2
Manuel
Radovanovic
www.manuelradovanovic.com

MyValueType2 after changed MyValueType1:
Manuel
Radovanovic
www.manuelradovanovic.com

--------------------

MyReferenceType1:
Manuel
Radovanovic
www.manuelradovanovic.com

MyReferenceType2:
Manuel
Radovanovic
www.manuelradovanovic.com

MyReferenceType2 after changed MyReferenceType1:
Bill
Gates
www.gatesnotes.com

Kako to sve izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Fundamentals - 24. Value And Reference Types )