C#

Mayıs 9, 2021

C#’ta Değişkenler (ValueType-Reference Type, Stack-Heap Kavramları, Boxing-Unboxing Kavramları ) [Veri Serisi – Değişkenler]

 

Herkese merhaba,

Hiç bilmeyenler için değişkenleri, yazılımda herhangi bir veriyi sakladığımız birer kutu gibi düşünebiliriz.

Credit: Steven Curtis

Gerçek hayattan kutu örneğiyle devam edersek; bu kutuların (değişken) içerisinde birer veri saklandığını (değişkenin değeri), kutuların farklı ebatlarda olabileceğini (değişken boyutu), saklanan her verinin farklı tiplerde (değişkenin türü) olabileceğini ve kutuların üstüne de birer isim yazdığımızı (değişkenin adı) düşünebiliriz.

Değişken Tipleri

Şimdi değişkenleri genel olarak bir tabloda, tip, boyut, aralık ve CTS karşılıkları olarak inceleyelim.

TİP BOYUT (Byte) ARALIK CTS Karşılıkları
byte 1 0-255 System.Byte
sbyte 1 -128 ile 127 System.Sbyte
short 2 -32768 ile 32767 System.Int16
ushort 2 0 ile 65535 System.Uint16
int 4 -2147483648 ile 2147483647 System.Int32
uint 4 0 ile 4294967295 System.Uint32
long 8 -9223372036854775808 ile 9223372036854775807 System.Int64
ulong 8 0 ile 18446744073709551615 System.Uint64
float 4 1.5 x 10-45 ile 3.4 x 1038 System.Single
double 8 5.0 x 10-324 ile 1.7 x 10308 System.Double
decimal 8 1.0 x 10-28 ile 7.9 x 1028 System.Decimal
bool 1 True veya False System.Boolean
char 2 U + 0000-U + FFFF System.Char
string önceden belirlenmemiştir Metin tutar, belirli bir aralığı yoktur

Yukarıdaki tabloda CTS (Common Type System) karşılıkları kısmında CTS kavramını ilk kez görenler, detaylar için  Bir .exe Uygulamasının Anatomisi (CLR, CIL, JIT, CTS Kavramları) başlıklı yazımdaki “CTS (Common Type System) Nedir?” kısmını okuyabilir.

Yukarıdaki tabloya bakarak gerçek hayattan örneklemeye devam edersek tip için kutunun tipini, boyut için kutunun ebatını, aralık için kutunun taşıyabileceği içeriğin hacminin en alt ve en üst limitlerini, CTS karşılıkları için de kutunun evrensel olarak kabul görmüş dünyanın neresine giderseniz gidin kutu dünyasında standartlaşmış bir adı olarak düşünebiliriz.

Akıllara hemen “C#’ta neden farklı farklı değişken tipleri ve bunların farklı boyutları, kapasiteleri var ki? Tek bir tane değişken türü olsa da bu kadar uğraşmasak olmaz mıydı?” gibi bir soru gelebilir. Elbette tek bir veri tipi olması biz yazılım geliştirenlerin işini bir hayli kolaylaştıracaktı ancak yazılım geliştirmede yalnızca kod yazan kişiler olarak kendi kolaylıklarımızdan sorumlu değiliz. Geliştirdiğimiz her yazılımın tükettiği kaynaklar mevcut. Tüketilen kaynakları optimum kullanmak da bizlerin sorumluluğu arasındadır. Elimizdeki kaynakları ne kadar iyi kullandığımız bizlerin ne kadar iyi birer yazılım geliştirici olduğunu gösteren bir faktördür. Önceden belirlenmiş değişken tiplerinin ve boyutlarının olmasının sebebi .NET Framework’ün, yazılım içerisinde kullanacağımız verinin tipini bilmek istemesinden kaynaklanmaktadır. .NET framework veri tipini bilmek istiyor çünkü elindeki memory kaynağını ona göre organize edecektir. Bu sebeple bu kadar farklı veri tipi ve önceden belirlenmiş standart boyutları ve aralıkları bulunmaktadır.

Gerçek hayattan örnek vermemiz gerekirse, evden eve taşıma yapan her şey dahil bir nakliye firmanızın olduğunu ve elinizde büyük küçük çeşitli kamyonetlerin, kamyonların, tırların yer aldığını düşünün. Bir müşterinin sizi aradığını ve eşyasını İstanbul’dan Hakkari’ye taşıtmak istediğini varsayalım. Firma olarak maliyeti belirlemek ve müşteriye de sunduğunuz hizmet için bir fiyat verebilmek için müşterinin eşyasının miktarını bilmeniz gerekir ki buna uygun kamyonet, kamyon veya tır seçip o eşyayı en uygun araca yükleyebilesiniz. Yalnızca bir koltuk ve bir televizyonu olan bir müşteri için koca bir tır’ı İstanbul’dan Hakkari’ye gönderir miydiniz? Yoksa daha uygun ve maliyetinizi azaltacak küçük bir kamyonet işinizi zaten çok güzel görmez miydi? Bu sayede siz kamyoneti yola çıkardığınızda çok daha fazla eşyası olan başka bir müşteri için tırınız hazırda beklerdi 🙂

İşte bu örnekten de anlaşılacağı üzere, .NET Framework de kod yazarken veriyi saklayacağı tipin kendisine bildirilmesini istiyor ki ona uygun hafızada yerini ayırabilsin. Kullanacağınız verinin tipine göre seçim yapmak oldukça isabetli olacaktır.

Value Type ve Reference Type Nedir?

C#’ta tipler “value type (değer tipi)” ve “reference type (referans tipi)” olarak ikiye ayrılır.

Value Type (Değer Tipi): C#’ta kullanılan value type’lar önceden boyutu kesin olarak belirlenmiş, içerisinde direkt olarak veri tutan tiplerdir. Yukarıdaki değişken tablosunda boyut sütununa bir bakalım. Boyutlarının kesin olarak byte karşılıkları yazan değişken tiplerinin hepsi (int, long, float, double, decimal, char, bool, byte, short) birer value type’dır.

Reference Type (Referans Tipi): İçerisinde direkt olarak veriyi değil, verinin tutulduğu hafıza adresini barındıran yani referansını tutan tiplerdir. Yine yukarıdaki değişken tablosuna baktığımızda string’in belirli bir boyutu olmadığını görürüz. Bu sebeple string’e value type diyemeyiz. string bir reference type’dır.

 

VERİ TİPLERİ
VALUE TYPES (DEĞER TİPLERİ) REFERENCE TYPE (REFERANS TİPLERİ)
int string
long object
float class
double interface
decimal array
char delegate
bool pointer
byte
short
struct
enum
GUID

Kod içerisinde bir tipin value type olup olmadığını öğrenmenin oldukça basit bir yöntemi vardır. Örneğin int tipinin kodda value type olup olmadığını aşağıdaki paylaştığım küçük kod parçası sayesinde öğrenebiliriz.

bool kontrol = typeof(int).IsValueType;

IsValueType property’si sayesinde bir tipin value type olup olmadığını kolayca öğrenebiliriz.

Stack ve Heap Kavramları Nedir?

Stack ve Heap, memory’de (RAM/bellek) bulunan mantıksal yapılardır. Bu yapıların detaylarına geçmeden önce stack’in kısıtlı ama hızlı, heap’in ise stack’e görece daha geniş bir alana ama yine stack’e göre daha yavaş bir yapıya sahip olduğunu bilmek işimize yarayacaktır.

Stack

  • Value Type‘lar (Değer Tipleri) Stack‘te tutulur.
  • Stack‘te veriler üst üste ve son giren ilk çıkar (LIFO – Last In First Out) mantığıyla tutulur ve sırası gelmeden aradaki bir değer ile işlem yapılmaz.
  • Stack’te bir veriye erişmek, Heap’e göre daha hızlıdır.
  • Oluşturulan veriler Stack’in kapsamında çıkınca otomatik olarak yok edilir.
  • Program çalışmadan önce Stack’te yer ayrılır. Eğer yazılımı geliştiren kişi tarafından bu bölüm aşılırsa meşhur Stackoverflow hatası ile karşılaşılır.

Heap

  • Reference Type‘ların (Referans tiplerin) değeri Heap‘te, değerin Heap‘te saklandığı adresin bilgisi ise Stack‘te tutulur. (Yani bir reference type saklanırken memory’nin hem Heap bölgesi hem de Stack bölgesi kullanılmaktadır. Dikkat edilmesi gereken referans tipin değerinin Heap’te saklanırken, o değerin adresinin Stack’te saklandığıdır.)
  • Heap’te veriler karışık bir şekilde tutulur, Stack gibi belirli bir sırada tutulmaz.
  • Heap bölgesindeki bir veriye erişmek, Stack’e oranla daha maliyetlidir (yavaştır).
  • Heap bölgesindeki bir verinin silinmesi C# için Garbage Collector algoritmasına bağlıdır.
  • Program çalıştırılmadan önce yer ayrılmaz, programın çalışma zamanında yer ayrılır.

Boxing ve Unboxing Kavramları Nedir?

Boxing 

Boxing işlemi, value type (değer tipi) bir değişkeni, reference type (referans tipi) bir nesneye aktarmaya denir.

int sayi = 123;   // value type bir degisken tanimlandi
object obje = sayi;  // bu atamada sayi degiskenine dolaylı olarak (implicity) boxing islemi uygulandi

Unboxing

Reference type (referans tipi) değişkenin işaret ettiği değeri, value type (değer tipi) bir değişkene aktarmaya denir.

int sayi1 = 123; //value type degisken tanimlandi ve degeri atandi
object obje = sayi1;  // Boxing islemi 
int sayi2 = (int)obje;  // Unboxing islemi

Not: Unboxing işlemi gerçekleştirilirken, boxing işleminde kullanılan veri tipinin aynısının kullanıldığına dikkat edilmelidir. Aksi hale veri tipleri uyuşmayacağından InvalidCastException hatası alınacaktır.

Boxing ve Unboxing Hakkında Ek Bilgiler

  • Boxing işlemi, normal bir atama işleminden 20 kat daha uzun sürmektedir.
  • Unboxing işlemi, normal bir atama işleminden 4 kat daha uzun sürmektedir.
  • Bu sebeplerden dolayı gerekli olmayan aşırı boxing ve unboxing kullanımı uygulamanızı gözle görülür biçimde yavaşlatacaktır.

 

Veri Serisi‘nin ilk makalesi olan Değişkenler’in böylece sonuna geldik. Herkese keyifli kodlamalar dilerim :)!

Ceyhun Çözvelioğlu

Coffee Lover and Software Developer

You may also like...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir