C# VERİ TİPLERİ

Üç boyutlu kök küre etrafında küp, küre, altıgen prizma ve elmas formlardan oluşan veri tipi hiyerarşisi

C# öğrenmeye yeni başlayanların büyük bölümü string'i bir temel tip sanır. int, double, bool gibi yazılır, atama sözdizimi aynıdır, ilk bakışta hiçbir fark görünmez. Oysa string aslında bir referans tipidir — bellekte değeri kendisi tutmaz, bir nesneye işaret eder. Bu ayrım eşitlik karşılaştırmasından metot parametresi davranışına, GC üzerindeki yükten null kontrolüne kadar pek çok davranışı belirler.

C#'ın yerleşik tip sisteminin neyi nasıl sakladığı bir kez netleştiğinde değişken kararları, parametre aktarımı ve bellek davranışı artık tahmin etmek zorunda kaldığınız konular olmaktan çıkar. Aşağıdaki bölümler temel tipleri, kategorilerini ve günlük kullanımda sık karşılaşılan tuzakları sırayla ele alıyor.

Değer Tipi ve Referans Tipi Ayrımı

C# tipleri iki ana kategoriye ayrılır. Değer tipi (value type) değişkenin kendisi içinde tutulur ve genellikle stack üzerinde saklanır. Referans tipi (reference type) ise heap üzerinde tutulan bir nesneye işaret eden referansı barındırır; değişken nesnenin kendisini değil adresini taşır.

Fark basit bir örnekte hemen ortaya çıkar:

  • int a = 5; int b = a; b = 10;a hâlâ 5'tir, çünkü b kopya aldı.
  • İki List değişkeni aynı nesneye işaret ediyorsa birinden eklenen eleman diğerinden de görülür — kopya değil, aynı nesne.

Değer tipi olanlar: tüm sayısal tipler, bool, char, struct ve enum. Referans tipi olanlar: string, object, sınıflar, diziler, delegeler ve interface'ler. Bu kategori, parametre olarak aktarıldığında nesnenin nasıl davranacağını doğrudan belirler.

Tam Sayı Tipleri

Tam sayı tutmak için kullanılan tipler birbirinden farklı genişlikte aralık sunar. Bellekten tasarruf etmek isteyenler dar tipi seçer, geniş aralık gerekenler büyük tipi tercih eder.

  • byte — 0 ile 255 arası, 8 bit
  • short — yaklaşık -32 bin ile 32 bin arası, 16 bit
  • int — yaklaşık ±2,1 milyar, 32 bit (varsayılan tam sayı tipi)
  • long — yaklaşık ±9 kentilyon, 64 bit
  • uint, ushort, ulong — işaretsiz sürümler (negatif değer almaz, üst sınırı iki katına çıkar)

Pratikte tercih çoğunlukla int'tir. Bellek kritik değilse, short veya byte seçmek erken optimizasyon olur. Microsoft'un yayımladığı resmi C# dil referansı her tipin tam aralığını ve özel kullanım notlarını ayrıntılı dokümante eder.

Ondalık Sayı Tipleri

Ondalık değerleri tutmak için üç farklı tip vardır ve aralarındaki fark sadece hassasiyet değildir.

  • float — 32 bit, ~7 basamak hassasiyet, sabit yazımda f son eki gerekir: 3.14f
  • double — 64 bit, ~15-17 basamak, varsayılan ondalık tip
  • decimal — 128 bit, ~28-29 basamak, finansal hesaplar için

Sık karşılaşılan bir hata: para hesabında double kullanmak. IEEE 754 standardı binary tabanlı çalışır ve 0.1 + 0.2 sonucu tam olarak 0.3'e eşit gelmez. Faturayı, maaşı, vergi hesabını decimal ile tut. Mühendislik hesabı, grafik koordinatı, fizik simülasyonu gibi geniş aralık ve hızın önemli olduğu yerlerde double tercih edilir.

Üç boyutlu value ve reference tip karşılaştırması, içinde küp ve okla işaret eden iki bellek bloku

Karakter Metin ve Boolean

char tek bir Unicode karakteri tutar, 16 bit genişliğindedir ve değer tipidir. Tek tırnak ile yazılır: char c = 'A';. string ise sıfırdan binlerce karaktere kadar metin tutabilir; çift tırnak ile yazılır ve içeride bir karakter dizisini sarmalar.

String referans tipi olmasına rağmen immutable'dır — bir kez oluşturulan string nesnesinin içeriği değişmez. Yeni bir karakter eklediğinizde aslında bellekte yeni bir string nesnesi yaratılır. Yoğun string birleştirme yapıyorsanız StringBuilder kullanmak performans açısından kritiktir.

bool yalnızca true veya false değerini alır. C, C++ veya JavaScript'ten gelenler için tuzak: C#'ta sayı bir bool yerine geçmez. if (sayi) doğrudan derlenmez; if (sayi != 0) yazmak gerekir.

Nullable Tipler

Değer tipleri varsayılan olarak null alamaz. int sayi = null; satırı derlenmez. Veritabanından gelen NULL değerleri, henüz girilmemiş yaş bilgisi gibi senaryolarda bu eksiklik problemli olur. Çözüm nullable sözdizimidir:

  • int? yas = null; — soru işareti ile nullable hâle gelir
  • int? x = 5; int y = x ?? 0; — null-coalescing operatörü ile varsayılan değer atanır
  • if (x.HasValue) { ... } — değer olup olmadığı kontrol edilir

int? aslında Nullable<int> yapısının kısa yazımıdır; derleyici ikisini de aynı türe çevirir. Referans tipleri ise C# 8 sonrasında nullable annotation ile yönetilir (string?), bu bir runtime davranışı değil derleyici uyarısı düzeyindedir.

Tip Dönüşümleri

Bir tipten diğerine geçiş üç ana yolla yapılır:

  1. Implicit (örtük) dönüşüm: Bilgi kaybı yoksa otomatik gerçekleşir. int'ten long'a geçiş gibi.
  2. Explicit (açık) cast: Bilgi kaybı riski varsa programcı açıkça belirtir. (int)3.7 ifadesi 3 döner; ondalık kısım atılır.
  3. Convert ve Parse metotları: Genellikle metinden sayıya geçişte kullanılır. int.Parse("42") başarılı; geçersiz metin atar.

Kullanıcıdan veya dış kaynaktan gelen metni sayıya çevirirken Parse yerine int.TryParse tercih edilir. Başarısız durumda exception fırlatmaz, false döner. Exception kontrolü pahalıdır; TryParse daha hızlı ve okunaklıdır.

Üç boyutlu tip dönüşüm akışı, kaynak kutudan hedef kutuya eğri ok ve soru işareti rozeti, mor tonlarda

var ve Tip Çıkarımı

var anahtar kelimesi tipi gizlemez, sadece yazmaktan kurtarır. Derleyici ifadenin sağ tarafına bakar, tipi otomatik çıkarır.

  • var liste = new List<string>(); — tip List<string> olarak belirlenir
  • var sayi = 42; — tip int olur
  • var sonuc; — derlenmez; çıkarım yapacak ifade yok

var dinamik tip değildir; derleme zamanı çıkarımıdır. Çalışma sırasında tip değişmez. Bu yönüyle JavaScript'in var'ı veya Python değişkenleri ile karıştırılmamalıdır. Çıkarılan tip kod okunurluğuna katkı sağladığında kullanın, anonim tipler ve LINQ sorgularında neredeyse zorunludur.

Yaygın Tuzaklar

Yeni başlayanların en sık takıldığı noktalar:

  • String karşılaştırmada referans yanılgısı: == operatörü string için içerik karşılaştırır (özel olarak), ama özel class'larda referans karşılaştırır. Belirsizlik varsa .Equals() kullan.
  • Ondalık sayıda f son ekini unutmak: float oran = 0.5; derlenmez; 0.5 varsayılan olarak double'dır. 0.5f yazmak gerekir.
  • Implicit cast'i sürpriz görmek: byte b = 200; byte c = (byte)(b + 100); sonucu 44 — taşma olur, exception atmaz. Aritmetik öncesi tip genişletmesini hesaba kat.
  • Null kontrolünü atlamak: Referans tipi parametresine gelen null üzerinde metot çağırmak NullReferenceException fırlatır. C# 8+ nullable annotation bu hatayı derleme zamanında yakalamayı kolaylaştırır.

C# tip sistemini örnek projelerle pekiştirmek isteyenler için C# eğitimi hem temel tipleri hem nesne tabanlı yapıları uygulamalı şekilde ele alır. Tip kararları küçük gibi görünse de yazılım büyüdükçe etkisini büyütür; doğru tipi baştan seçmek sonradan refactor etmekten her zaman ucuzdur.