Giriş
Modern yazılım geliştirmede immutable pattern, güvenli ve sürdürülebilir kod yazmanın temel taşlarından biridir. Bu pattern, nesne oluşturulduktan sonra durumunun değiştirilemez olmasını sağlar.

Immutable nesneler, özellikle çok iş parçacıklı uygulamalarda kritik öneme sahiptir. Thread safety sorunlarını ortadan kaldırırken, kodun öngörülebilirliğini artırır.
Bu rehberde, immutable object pattern‘inin C# ile nasıl uygulanacağını öğreneceksiniz. Temel kavramlardan başlayarak, ileri seviye tekniklere kadar kapsamlı bir bakış açısı sunacağız.
Temel Bilgiler
Immutable Nedir?
Immutable, Türkçe karşılığı “değişmez” olan bir kavramdır. Bir nesne immutable olduğunda, oluşturulduktan sonra iç durumu hiçbir şekilde değiştirilemez.
Temel Özellikler
Immutable pattern‘in temel özellikleri şunlardır:
- Nesne oluşturulduktan sonra değiştirilemez
- Tüm alanlar readonly veya private olmalıdır
- Setter metodları bulunmaz
- Thread-safe yapıdadır
Basit Immutable Sınıf Örneği
public class Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
Bu örnekte Person sınıfı immutable‘dır. Özellikler sadece constructor ile atanabilir ve sonrasında değiştirilemez.
Avantajları
Immutable pattern kullanmanın başlıca avantajları:
- Thread Safety: Çoklu iş parçacığında güvenli kullanım
- Öngörülebilirlik: Nesne durumu sabit kalır
- Hashing: Dictionary ve HashSet kullanımında güvenli
- Debugging: Hata ayıklama sürecinde kolaylık
Orta Seviye Detaylar
Derin Immutability
Pattern‘in doğru uygulanması için sadece primitive tipler yeterli değildir. Referans tipleri de immutable olmalıdır.
public class Address
{
public string City { get; }
public string Country { get; }
public Address(string city, string country)
{
City = city;
Country = country;
}
}
public class Employee
{
public string Name { get; }
public Address WorkAddress { get; }
public Employee(string name, Address address)
{
Name = name;
WorkAddress = address; // Address de immutable olmalı
}
}
Collection’lar ile Çalışma
Immutable nesnelerde koleksiyonlar özel dikkat gerektirir:
public class Department
{
private readonly List<string> _employees;
public IReadOnlyList<string> Employees => _employees.AsReadOnly();
public Department(IEnumerable<string> employees)
{
_employees = employees.ToList();
}
}
Builder Pattern ile Kombinasyon
Karmaşık immutable nesneler için Builder pattern kullanılabilir:
public class Product
{
public string Name { get; }
public decimal Price { get; }
public string Category { get; }
private Product(string name, decimal price, string category)
{
Name = name;
Price = price;
Category = category;
}
public class Builder
{
private string _name;
private decimal _price;
private string _category;
public Builder SetName(string name)
{
_name = name;
return this;
}
public Builder SetPrice(decimal price)
{
_price = price;
return this;
}
public Builder SetCategory(string category)
{
_category = category;
return this;
}
public Product Build()
{
return new Product(_name, _price, _category);
}
}
}
Record Types (C# 9.0+)
Modern C# ile immutable pattern uygulaması daha kolaydır:
public record PersonRecord(string Name, int Age);
public record AddressRecord(string City, string Country);
public record EmployeeRecord(string Name, AddressRecord Address);
Record types otomatik olarak immutable yapı sağlar ve pattern uygulamasını basitleştirir.
Structural Equality
Immutable nesnelerde değer karşılaştırması önemlidir:
public class ValueObject
{
public string Value { get; }
public ValueObject(string value)
{
Value = value;
}
public override bool Equals(object obj)
{
if (obj is ValueObject other)
return Value == other.Value;
return false;
}
public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
}
}
Performance Optimizasyonları
Immutable pattern kullanırken performans için dikkat edilmesi gerekenler:
- String Interning: Tekrarlanan string değerler için
- Lazy Loading: Hesaplanan özellikler için
- Caching: Pahalı işlemler için
public class OptimizedImmutable
{
private readonly Lazy<string> _expensiveValue;
public string ExpensiveValue => _expensiveValue.Value;
public OptimizedImmutable(string input)
{
_expensiveValue = new Lazy<string>(() =>
ComputeExpensiveOperation(input));
}
private string ComputeExpensiveOperation(string input)
{
// Pahalı işlem
return input.ToUpper();
}
}
Functional Programming Entegrasyonu
Immutable pattern, fonksiyonel programlama yaklaşımları ile uyumludur:
public static class ImmutableExtensions
{
public static Person WithName(this Person person, string newName)
{
return new Person(newName, person.Age);
}
public static Person WithAge(this Person person, int newAge)
{
return new Person(person.Name, newAge);
}
}
// Kullanım
var originalPerson = new Person("Ahmet", 30);
var updatedPerson = originalPerson.WithAge(31);
Sonuç
- Immutable object pattern, modern C# geliştirmede vazgeçilmez bir pattern‘dir. Kod güvenliğini artırırken, hata potansiyelini azaltır.
- Bu pattern‘in doğru uygulanması, özellikle çok iş parçacıklı uygulamalarda kritik öneme sahiptir. Record types ile birlikte, C#’da immutable nesne oluşturma süreci oldukça basitleşmiştir.
- Immutable pattern kullanırken, performans ve bellek yönetimi konularını da göz önünde bulundurmak önemlidir. Lazy loading ve caching teknikleri ile optimize edilmiş çözümler geliştirilebilir.
- Son olarak, immutable yaklaşımı benimserken, projenizin gereksinimlerini değerlendirmeyi unutmayın. Her durumda immutable pattern uygun olmayabilir, ancak çoğu senaryoda güvenli ve sürdürülebilir kod yazmanıza yardımcı olacaktır.
Kaynakça
- c-sharpcorner – C# 11 – Immutable Object Pattern
- codeproject – C#11 – Immutable Object Pattern
- stackoverflow – Immutable object pattern in C#