Referans Nedir?
🔸Ram'in Stack bölgesinde tanımlanan ve Heap bölgesindeki nesneleri işaretleyen (referans eden) değişkenlerdir/noktalardır.
🔸Normalde Stack'te integer, boolean, char vb. değer türlü tüm değişkenlerin değerlerini tutabiliyoruz. Ama referans türlü değişkenlere geçtiğimizde değerler Heap'te, referanslar Stack'te tutuluyor. Bu referans şu yapılar ile oluşturulabilir: class, interface, abstract class.
📌Not: Bu yapılanmalara ek olarak C# 9.0 ile record yapılanması da gelmiştir. Aşağıda Heap bölümünde gösterilenlerle aynı şekilde record MyRecord{ } kullanılır.
✨Class, interface ve abstract class'tan referans oluşturulur, daha sonra polymorphism sayesinde bunlardan üretilmiş bir nesne referans edilir. Ancak örn. yukarıda MyAbstractClass'tan oluşturulmuş bir referans ile abstract class'tan üretilmiş bir nesne temsil edilemez. Kısacası akraba olarak kabul edebileceğimiz ama esasında farklı yapılanmaları olan bu kavramlar aracılığıyla referans oluşturabilsek de bu referanslarla sadece class'tan oluşturulmuş nesneleri işaretleyebiliriz. İleride bu yapılanmalar öğrenildiğinde durum netleşecektir.
✨Referanslar bir nesne referans etmek zorunda değillerdir. Bir referans, herhangi bir nesne işaretlemeyecek şekilde oluşturulduğunda default olarak null değerini taşır. (Sayısal değerlerde 0, boolean ise False vb.)
Stack - Heap İlişkisi
Bu bir nesne operatörüdür:
MyClass m = new MyClass( );
Burada Compiler üzerinden new talep edilmiş, talep edilen nesne MyClass türünden ve bu nesne Stack'teki MyClass türüne m üzerinden referans ile işaretlenmiş. Daha detaylı inceleyelim:
🔹Konseptin sol tarafı referansı temsil ediyor. Stack'te m referans noktası ile bir referans oluşturulmuş.
🔹Sağ taraf ise new operatörü içeriyor ve new, yanında bulunan tür ne ise o türde nesne oluşturmamızı sağlar. Daha sonra oluşturulan bu nesne Heap'e gönderilir.
🔹" = " operatörü nesne tabanlı programlamada işaretleme anlamında kullanılır. Burada da üretilmiş bir nesneyi bir referans ile işaretlerken kullanılmış.
Bu konsept sayesinde m ile Heap üzerindeki nesneye rahatça erişebiliriz.
✨Nesne üzerindeki elemanlara nesne üzerinden erişilir. Artık m. yazdığımızda m nesnesinin dışarıdan erişime açık olan elemanlarına erişebiliriz.
📌Not: " . " member access operatörüdür.
1. Access ile eriştiğimiz elemanda işlem yaptığımız bir örnek görelim:
MyClass m = new MyClass( );
m.MyProperty = 10;
Heap'teki nesne m ile işaretlendi. m. ile MyProperty elemanına ulaşıldı ve 10 değeri atandı.
2. Herhangi bir nesneyi işaretlemeyen bir referans örneği:
MyClass m2 = null;
m2.MyProperty = 20;
Nesne işaretlenmediğinde default olarak null olur. Null olma durumunda access modifier ile nesne elemanlarına erişim sağlansa da elemanlarla ilgili işlem yapılamaz, "null reference" hatası alınır.
Referanssız Nesneler
🔸Bir nesne herhangi bir referans ile işaretlenmek zorunda değildir. Nesne oluşturulduğunda eğer bir referans ile işaretlenmezse Heap'e yerleştirilir, ancak bu nesneye bir daha erişilemez. (Çünkü Heap'teki nesneye Stack üzerinden referans gösterme harici erişimimiz yoktur.) Dolayısıyla daha sonra erişmek için oluşturulma anında müdahale edilmeli.
new MyClass( );
🔸Referanssız nesneler, memory üzerinde gereksiz yer kaplayacağından dolayı bir süre sonra "Garbage Collector" yapılanması ile imha edilir. Garbage Collector bir tür bellek yöneticisidir.
Referans Türüne Göre Nesne Elemanlarına Erişim
🔹Her bir referans, bir nesneyi temsil edebilecek imzaya sahiptir. Elimizde MyClass adında/türünde bir class olsun ve a, b, c elemanlarını içersin. Buradan oluşturduğumuz nesnenin Heap'te oluşturulduğunu görmüştük. Artık member access operatörü ile ulaşmaya çalıştığımızda ulaştığımız elemanlar, ilgili nesnenin türüne de uygun olduğu için Heap'teki elemanlara karşılık gelmektedir. Kısacası referans türünde a, b, c olduğu için nesnenin içerisindeki a, b, c'ye erişebiliyoruz. Bu konu inheritance, polymorphism ve abstraction konularına gelindiğinde daha net anlaşılacaktır.
✨Referansta sadece a, b varken nesnede a, b, c olduğu bir durumda referans üzerinden sadece nesnedeki a ve b'ye erişilebilir. Bu da abstraction konusuna giren bir durum.
Object Initializer ile Nesne Oluştururken Propertylere İlk Değeri Atama
Object initializer kullanımı böyledir:
MyClass m = new MyClass( )
{
MyProperty = 10
};
Bu şekilde nesne oluşturulurken ilk değeri verilerek oluşturulur.
Örneklendirelim: Bu şekilde bir class'ımız olsun:
Nesne oluştururken ilk elemanları bu şekilde verebiliriz:
✨Nesne elemanlarının nesne oluşum aşamasında tanımlanması ile sonradan değer atanması farklıdır. Daha sonra referans ile ilgili propertyler değiştirilebilir ve bu bir soruna yol açmaz. Ancak nesne tanımlarken verdiğimiz değerler o nesnenin default değerleri olarak tutulur.
✨Referans kullanmadan oluşturduğumuz bir nesnenin değerlerini normalde atayamıyorduk. Bu şekilde tanımlamamız mümkün. Ancak yine de referanssız nesnelere daha sonra erişim sağlanamayacak ve bir süre sonra Garbage Collector tarafından silinme işlemi gerçekleşecektir.
-ˋˏ ༻ ☕ ༺ ˎˊ-
çokzel bir paylaşım olmuş like attım
YanıtlaSilAy teşekkürler sevgili okuyucularım, beni sizler var ettiniz 🎔
Sil