referencetype-adrese-gore-otürülmür!

Referencetype adresə görə ötürülmür!

                C# dilini öyrənənlərin çox zaman yanıldıqları məsələlərdən biri reference type(linkvari tip) və valuetype(qiymətalabilən tip)-la bağlıdır. Yalnışlığın səbəbi Reference type-in linkə görə , valuetype isə qiymətə görə ötürülməsi fikridir. Bu postda bu məsələyə aydınlıq gətirməyə çalışacağıq.

               Hərşey əslində necə başlayır..

C# dilini öyrənərkən ilk başlarda rastlaşdığımız mövzulardan biri məhz Stek və Hipin(Heap) işləməsini göstərən, tipləri bu yaddaş modellərinə görə qruplaşdıran mövzudur. Mövzunun məğzində dəyişən tiplərini 2 əsas kategoriyaya ayırmaq , Stek vəHipdə dəyişənlərin necə rəftar etdiyini göstərməkdir.

               Stack(Stek) və Heap(Hip)

.NET platformasında dəyişənlər Stek və Hipdə saxlanıla bilir. Qiymətalabilən tiplər hamısı (int, uint,long,ulong,short,ushort,byte,sbyte,char,bool,decimal,double,float) Stek yaddaş modelinə görə saxlanılır. Stek yaddaş sahəsi kiçikhəcmli məlumatları saxlaya bilir amma Heap-ə nisbətən çox sürətli işləmə qabiliyyətinə malikdir.

               Heap yaddaş sahəsində isə əsasən ReferenceType(linkvari) tiplər saxlanılır. Bunlara class,interface,delegate,array,object,string-i aid etmək olar. Bu obyektlərin özü Heapdə saxlanılsa da onların adresi yenə də Stekdə saxlanılır! Heap yaddaş sahəsi Stekə nisbətən daha böyük datalarla işləyə bilsə də sürət baxımından ondan geri qalır.

 class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee
            {
                Id = 1,
                Name = "Jonathan"
            };
        }
    }

Əgər yuxarıdakı kodu yaddaşda təsvir etsək belə bir görüntü ortaya çıxır.

Şəkildən göründüyü kimi, obyekt yaradılan zaman ona Heap yaddaş sahəsində yer ayrılır.

Tiplərin arqument olaraq ötürülməsi aksiomu..

               Tipin adına uyğun olaraq çox zaman belə bir illuziya yaranır ki, əgər qiymətalabilən tipdirsə(valuetype) deməli hər hansı metoda arqument kimi ötürülən zaman qiymət ötürülür, linkvari tipdirsə(referenceType) deməli linkə görə yəni adresə görə ötürülür.


`Qayıdında nolub sizə?!` və ya “Məsələ bildiyin kimi deyil”..

Şəkildən göründüyü kimi, linkvari tiplərin obyektləri Heap yaddaş sahəsinə düşür, amma onların adresləri stekdə qalır. Əgər bir metoda arqument olaraq referenceType versək həmin tip deyişikliyə məruz qalır və bu bizdə adresə görə ötürülmə illuziyası yaradır.

 static void Main(string[] args)
        {
            Employee employee = new Employee
            {
                Id = 1,
                Name = "Jonathan"
            };

            WriteLine($"Before : {employee.Name}");

            ChangeEmployeeName(employee);
            WriteLine($"After : {employee.Name}");

            ReadLine();

        }
        static void ChangeEmployeeName(Employee employee)
        {
            employee.Name = "Simon";
        }

Şəkildən göründüyü kimi, əgər bir metoda referenceType veririksə həqiqətən həmin tip dəyişikliyə məruz qalır. Çox insan bu fikirdən yola çıxaraq referenceType linkə görə ötürülür qənaətinə gəlir..

   Məsələ odur ki, stek yaddaş sahəsinə referenceType-in adresi düşür və bir metod linkvari tipi arqument olaraq çağırdığı zaman stek-də əldə olan yalnızca adres olduğuna görə QİYMƏT OLARAQ ADRESİ göndərir.

               .NET-də bütün tiplər, istər stek istər hip tipləri olsun, hamısı qiymətə görə ötürülür!!


Səni inandırmağa çalışmaq...

Sual 1.Əgər referenceType adresə görə ötürülürsə ozaman niyə bu kod gözlədiyimiz nəticəni vermir?

Əgər adresə görə ötürmə anlayışı doğru olsaydı ozaman “Simon” sözü ekranda görünərdi. Sadəcə metod işə düşəndə köhnə yaddaş sahəsi dəyişilmədən qalır və dəyişənə yeni yaddaş sahəsi təyin olunur. Metod işini bitirdikdən sonra həmin yaddaş GC tərəfindən təmizlənəcək. Biz isə köhnə yaddaşa müraciət edərək qiymətin dəyişilib dəyişilmədiyini yoxlayırıq.

Sual2. Əgər referenceType adresə görə ötürülürsə ozaman aşağıdakı kod nəyə görə ötürülür bəs?

 static void Main(string[] args)
        {
            Employee employee = new Employee
            {
                Id = 1,
                Name = "Jonathan"
            };

            WriteLine($"Before : {employee.Name}");

            ChangeEmployeeName(ref employee);
            WriteLine($"After : {employee.Name}");

            ReadLine();

        }

        //əsl adresə görə ötürülmə prosesi ref və out açar sözləri ilə olur
        static void ChangeEmployeeName(ref Employee employee)
        {
            employee = new Employee
            {
                Name = "Simon"
            };
          
        }

Deyəcəksənki adresin adresinə görə ötürmə prosesi

Əgər tipləri adresə görə ötürmək lazımdırsa ozaman ref və out açar sözlərindən istifadə edəcəyik.

Növbəti məqaləmizdə bu açar sözlərinin iş funksiyası haqda danışacağıq.

Tural

Tural Süleymani

Süleymani Tural Microsoft-un MCSD statuslu mütəxəssisidir, 2008-ci ildən bu yana proqramlaşdırma üzrə tədris aparır

Müəllifin bu dildə ən son postları

Bu yazıları da bəyənə bilərsiniz