Mayıs 9, 2021

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

Okuma süresi: 5 dakika

 

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İPBOYUT (Byte)ARALIKCTS Karşılıkları
byte10-255System.Byte
sbyte1-128 ile 127System.Sbyte
short2-32768 ile 32767System.Int16
ushort20 ile 65535System.Uint16
int4-2147483648 ile 2147483647System.Int32
uint40 ile 4294967295System.Uint32
long8-9223372036854775808 ile 9223372036854775807System.Int64
ulong80 ile 18446744073709551615System.Uint64
float41.5 x 10-45 ile 3.4 x 1038System.Single
double85.0 x 10-324 ile 1.7 x 10308System.Double
decimal81.0 x 10-28 ile 7.9 x 1028System.Decimal
bool1True veya FalseSystem.Boolean
char2U + 0000-U + FFFFSystem.Char
stringönceden belirlenmemiştirMetin 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İ)
intstring
longobject
floatclass
doubleinterface
decimalarray
chardelegate
boolpointer
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.

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.

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.

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 :)!

Share

Ceyhun Çözvelioğlu

Coffee Lover and Software Developer

You may also like...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.