January 29, 2026 (3mo ago)

Sınıflar vs Yapılar: Bir Geliştiricinin Performans Rehberi

Sınıflar ile yapılar arasındaki temel farkları ortaya çıkarın. C#, Swift, C++, ve daha fazlasında yüksek performanslı, temiz kod için her birini ne zaman kullanacağınızı öğrenin.

← Back to blog
Cover Image for Sınıflar vs Yapılar: Bir Geliştiricinin Performans Rehberi

Sınıflar ile yapılar arasındaki temel farkları ortaya çıkarın. C#, Swift, C++, ve daha fazlasında yüksek performanslı, temiz kod için her birini ne zaman kullanacağınızı öğrenin.

Sınıflar vs Yapılar: Bir Geliştiricinin Performans Rehberi

Özet: Sınıflar ile yapılar arasındaki temel farkları ortaya çıkarın. C#, Swift, C++, ve daha fazlasında yüksek performanslı, temiz kod için her birini ne zaman kullanacağınızı öğrenin.

Giriş

Sınıflar ile yapılar arasındaki temel fark basit ama belirleyicidir: sınıflar referans tipleridir ve yapılar değer tipleridir. Bu ayrım, C#, C++, ve Swift gibi dillerde bellek düzenini, kopyalama davranışını ve çalışma zamanı performansını belirler. Hangisini ne zaman seçeceğinizi anlamak, öngörülebilir kod ve yüksek performanslı sistemler için elzemdir.

Temel Farkı Anlamak

Bir sınıfı örneklediğinizde, elinizde tuttuğunuz değişken, yığında (heap) bulunan nesneye işaret eden bir referanstır. O değişkeni kopyalamak, referansı kopyalar; birden fazla referans aynı nesneye işaret edebilir, bu yüzden bir referans üzerinden yapılan değişiklikler diğerleri tarafından görülebilir. Bu referans semantiği, sınıfların kimliğe (identity) sahip varlıklar için kullanılmasının ana nedenlerinden biridir.1

Bir yapı ise verinin kendisini temsil eder. Bir yapı oluşturmak, genellikle yığında değil de yığın (stack) üzerinde veya diziler içinde satır içi olarak saklanan değerlerden oluşan somut bir paket üretir; bu nedenle bir yapıyı kopyalamak bağımsız bir çoğaltım verir. Kopyayı değiştirmek orijinali etkilemez, bu da yapıları basit, değiştirilemez değerler için mükemmel kılar.1

Kapsülleme ve nesne tasarımı hakkında daha fazla bilgi için nesne yönelimli kapsülleme kılavuzumuza bakın: https://cleancodeguy.com/blog/object-oriented-encapsulation.

Yığın üzerinde saklanan Yapıları ve Yığından (Heap) referanslanan Sınıfları gösteren diyagram.

Hızlı Karşılaştırma: Referans vs Değer Tipleri

ÖzellikSınıf (Referans Tipi)Yapı (Değer Tipi)
Bellek konumuYığın (Heap); nesne işaretçi ile referanslanır.Yığın (Stack) veya satır içi; değişken veri kendisidir.
AtamaNesneyi değil referansı kopyalar.Tüm değeri kopyalar.
ÖmürÇöp toplayıcı tarafından yönetilir (veya bazı dillerde manuel silme).Kapsam dışına çıkınca veya satır içi saklandığında serbest bırakılır.
Kimlik vs değerKimliği vardır; birden fazla referans tek bir örneğe işaret edebilir.Bir değeri temsil eder; eşitlik genellikle verilere dayanır.

Paylaşılan kimliğe ihtiyaç duyduğunuzda sınıf kullanın. Yan etki olmadan kopyalanabilen basit, kendi içinde bütün bir değere ihtiyaç duyduğunuzda yapı kullanın.

Bu temel, yığın vs yığın (heap) tahsisi, önbellek yerelliği ve çöp toplama baskısı gibi daha derin performans takaslarını şekillendirir — bunları aşağıda inceliyoruz.

Bellek Tahsisi Hızın Nasıl Belirlenir

Bellek düzeni, CPU verimliliğini, işlem hacmini ve gecikmeyi etkiler. Bir sınıfa erişim genellikle bir dolayım içerir: yığın üzerinde bir işaretçi, veriyi yığındaki (heap) nesneye referanslar. Bu ekstra arama maliyet ekler ve önbellek davranışını olumsuz etkileyebilir. Değişkenin bulunduğu yerde doğrudan saklanan yapılar genellikle bu dolayımı önler ve daha iyi önbellek yerelliği sağlayan daha sıkı bellek düzenlerine izin verir.1

Sıkışık bellek, çöp toplama ve hız farklarını vurgulayarak Yapı/Yığın ve Sınıf/Yığın (Heap) bellek tahsisini karşılaştıran diyagram.

Çöp Toplama Maliyetleri

Yığındaki (heap) nesneler çöp toplamaya tabidir. GC döngüleri yürütmeyi duraklatabilir ve gerçek zamanlı veya yüksek verimli sistemlerde gecikmeyi artırabilir. Kısa ömürlü sınıf nesnelerinin sık tahsisi, GC baskısını ve CPU yükünü artırır. Çok sayıda küçük, kısa ömürlü nesne için değer tipleri kullanmak yığın hareketliliğini (heap churn) ve GC işini azaltır.3

Yığın tahsisi potansiyel GC yükü ekler. Yapılar, değer tabanlı ve kutulanmamış (unboxed) kaldıkları sürece bu yükten kaçınır.

Bu, ölçek ve yanıt verme için tasarlanmış sistemlerde özellikle önemlidir — tahsisleri azaltmak doğrudan GC etkinliğini azaltır ve çalışma zamanı performansını dengeler.

Önbellek Yerelliği ve İşlem Hacmi

Modern CPU’lar önbelleklere dayanır. Yapıların diziler halinde ardışık düzenlenmesi önbellek isabetlerini ve işlem hacmini artırır. Her sınıf örneği için ayrı yığın tahsisi verileri bellek boyunca dağıtır, önbellek kaçışlarını artırır ve işleme hızını düşürür. Sık döngüler ve veri işleme boru hatları için ardışık değer düzenleri büyük bir avantajdır.5

Kutulama (Boxing) Tuzakları

Bir değer tipi bir referans tipine dönüştüğünde (örneğin, nesne bekleyen bir koleksiyona konulduğunda) kutulama (boxing) oluşur. Kutulama bir yığın nesnesi tahsis eder ve değeri içine kopyalar; bu, yapının performans avantajlarını iptal eder ve GC yükünü artırır. Kutulamadan kaçınmak, verimli değer-tipi kullanımı için temel bir ilkedir.4

Diller Nasıl Farklılık Gösterir: C#, C++, ve Swift

Farklı diller farklı gelenekler ve yetenekler uygular. Dil-spesifik kuralları bilmek, bir dilin kurallarını körü körüne başka bir dile uygulamaktan kaçınmanıza yardımcı olur.

Referans vs değer tipleri ve nesne esnekliğine odaklanan C#, C++, ve Swift programlama dili özelliklerini karşılaştıran diyagram.

C#: Net Referans vs Değer Modeli

C#'ta class = referans tipi ve struct = değer tipidir. Kimliğe sahip varlıklar için sınıfları kullanın (örneğin Customer veya DatabaseConnection) ve küçük, değiştirilemez değerler için yapıları kullanın (örneğin Point, Color). Yapıları küçük ve değiştirilemez tutmak, ince hatalı davranışları ve kopyalama yükünü önler.1

Yaygın hatalar arasında büyük veya değiştirilebilir yapılar oluşturmak vardır; her ikisi de şaşırtıcı hatalara veya performans gerilemelerine yol açar. C#’ta optimize ederken değiştirilemez, küçük-yapı yönergesine uyun.

C++: Dil Kısıtlamasından Çok Gelenek

C++’ta struct ve class arasındaki tek sentaktik fark varsayılan erişim düzeyidir. Her ikisi de yığın veya yığında tahsis edilebilir, metotlara sahip olabilir ve kalıtımı destekleyebilir. Gelenek, düz veri kümeleri için struct, kapsüllenmiş nesneler ve RAII kaynak yönetimi için class kullanmaktır.

Bu esneklik, C++ geliştiricilerinin değer/referans ayrımlarını dil tarafından zorlanmış kurallara değil, geleneklere ve tasarım seçimlerine dayanarak yönetmeleri gerektiği anlamına gelir. Çok biçimlilik (polymorphism) ve kalıtım desenleri için rehberlik almak isterseniz, C++ tasarım notlarımıza bakın: https://cleancodeguy.com/blog/polymorphism-vs-inheritance.

Swift: Varsayılan Olarak Değer Odaklı

Swift, özel tiplerin çoğu için yapıları tercih etmeyi teşvik eder. Swift’teki yapılar metotları, uzantıları ve protokol uygunluğunu destekler; bu onları güçlü ama güvenli varsayılanlar yapar. Referans semantiği, kimlik veya Objective-C birlikte çalışabilirliği gerektiğinde yalnızca sınıfları seçin.2

Bu değer-öncelikli tasarım, özellikle eşzamanlı (concurrent) kodda veri akışını anlamayı kolaylaştıran değişmezlik (immutability) ve daha basit muhakeme teşvik eder.

Maksimum Verimlilik İçin Ne Zaman Yapı Seçilmeli

Yapılar, kimliği tamamen değerleriyle tanımlanan küçük, değiştirilemez veri paketleri için idealdir. Tipik örnekler:

  • Geometrik veriler: Point2D veya RGBColor
  • Finansal değerler: Money (tutar + para birimi)
  • Yüksek işlem hacimli boru hatlarında (pipeline) kullanılan küçük DTO’lar

Pratik bir boyut yönergesi “16–32 bayt” kuralıdır: eğer bir yapının alanları kabaca bu aralığa sığıyorsa, kopyalama maliyeti ılımlıdır ve genellikle yığın tahsisine kıyasla daha ucuzdur. Bir yapı daha büyük hale gelirse veya değiştirilebilir olması gerekirse, sınıf muhtemelen daha iyi bir seçimdir.5

RGB, 2D Nokta ve Para gibi küçük, değer-tipi veriler için yapı seçimini ve 16 bayt yönergesini gösteren rehber.

Değişmezlik ve Boyut Kuralları

  • Değiştirilemez yapıları tercih edin: değerler bir kez oluşturulmalı ve yerine konmalı, doğrudan değiştirilmemelidir.
  • Yapıları küçük tutun: büyük yapıları sık kopyalamak, referans geçmenin maliyetinden daha pahalı olabilir.

Bu kurallar, değiştirilebilir kopyalardan kaynaklanan gizli hatalardan ve aşırı kopyalama veya kutulama nedeniyle oluşan performans tuzaklarından kaçınmaya yardımcı olur.

Yaygın Tuzaklar ve Yeniden Düzenleme (Refactoring)

İki yaygın problem, değiştirilebilir yapılar ve aşırı kutulamadır.

Değiştirilebilir yapılar, değişikliklerin yalnızca bir kopyayı etkilemesi nedeniyle şaşırtıcı davranışlara yol açar. Değiştirilebilir yapıları, durum değişiklikleri için yeni örnekler döndüren değişmez olanlara yeniden düzenleyin.

Kutulama (boxing) birçok API ve koleksiyonda örtük olarak gerçekleşir; kutulama noktalarını tespit edin ve kaldırın ki yapıların performans avantajları korunabilsin.

Örnek: Değiştirilebilir Bir Noktayı (Point) Değişmez Bir Yapıya Yeniden Düzenleme (C#)

// PITFALL: Mutable struct public struct MutablePoint { public int X { get; set; } public int Y { get; set; }

public void Move(int dx, int dy)
{
    X += dx;
    Y += dy;
}

}

// REFACTOR: Immutable struct public readonly struct ImmutablePoint { public int X { get; } public int Y { get; }

public ImmutablePoint(int x, int y)
{
    X = x;
    Y = y;
}

public ImmutablePoint MovedBy(int dx, int dy)
{
    return new ImmutablePoint(X + dx, Y + dy);
}

}

Bu yeniden düzenleme niyeti (intent) belirginleştirir ve kazara durum bozulmasını ortadan kaldırır. Daha fazla temiz kod uygulaması için prensipler kılavuzumuza bakın: https://cleancodeguy.com/blog/clean-coding-principles.

Sıkça Sorulan Sorular (Kısa Soru-Cevap)

S1: Bir yapı yerine ne zaman sınıf tercih etmeliyim?

C: Tip küçük, değiştirilemezse ve bir kimlikten ziyade bir değeri temsil ediyorsa yapıyı tercih edin. Yapılar, noktalar, renkler veya küçük DTO’lar gibi basit veriler için mükemmeldir.

S2: Hangi performans tuzaklarına dikkat etmeliyim?

C: Değiştirilebilir yapılardan, büyük yapılardan (kopyalama maliyeti) ve kutulamanın yığın nesnelere neden olmasından kaçının—bunlar değer tiplerinin faydalarını yok eder ve performansa zarar verebilir.

S3: Dil farklılıkları seçimimi nasıl etkiler?

C: Dil geleneklerine uyun: C# değer vs referans tiplerini zorunlu kılar; C++ gelenek kullanır; Swift varsayılan olarak değer tiplerini tercih eder. Dil kurallarını öğrenin ve platform kısıtlarını anlamadan çapraz-dil kalıpları uygulamayın.12


Clean Code Guy olarak, bu ilkeleri gerçek kod tabanlarına uygulamanıza yardımcı oluyoruz. Kod Tabanı Temizlemelerimiz ve AI-Hazır Yeniden Düzenlemelerimiz yazılımı daha hızlı, daha güvenli ve bakımı daha kolay hale getirir. Daha fazla bilgi için ziyaret edin: https://cleancode.com.

1.
Microsoft Docs, “Choosing between classes and structs,” https://learn.microsoft.com/en-us/dotnet/standard/choosing-between-class-and-struct
2.
Apple Developer Documentation, “Structures and Classes,” https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
4.
5.
NDepend Blog, “Class vs Struct in C#: Making Informed Choices,” https://blog.ndepend.com/class-vs-struct-in-c-making-informed-choices/
← Back to blog
🙋🏻‍♂️

AI kod yazar.
Siz onu uzun süre dayanır hale getirirsiniz.

AI hızlanması çağında, temiz kod sadece iyi bir uygulama değil — ölçeklenen sistemlerle kendi ağırlığı altında çöken kod tabanları arasındaki farktır.

Sınıflar vs Yapılar: Bir Geliştiricinin Performans Rehberi | Clean Code Guy