C# ve .NET [7]

Giriş: Veriye Kontrollü Erişim İhtiyacı ve Kapsülleme Nesne Yönelimli Programlamanın temel hedeflerinden biri, bir nesnenin iç durumunu (verilerini) korumak ve dış dünyadan gelen doğrudan, kontrolsüz erişimi engellemektir. Bu prensibe Kapsülleme (Encapsulation) denir. Kapsülleme, ilgili verileri (alanları) ve bu veriler üzerinde çalışan metotları bir sınıf içinde bir araya getirmek ve genellikle verilere erişimi kısıtlayıp (örneğin private yaparak), bu verilere sadece sınıfın kendi metotları veya kontrollü arayüzleri (özellikler gibi) üzerinden erişilmesini sağlamaktır. Neden Doğrudan Alan Erişimi Kötü Bir Fikirdir? Eğer bir sınıfın alanlarını public yaparsak: public class YanlisOgrenci { public string Ad; // Public alan - KÖTÜ! public int Yas; // Public alan - KÖTÜ! } // Kullanım: YanlisOgrenci ogr = new YanlisOgrenci(); ogr.Ad = "Ali"; ogr.Yas = -5; // Geçersiz bir değer doğrudan atanabiliyor! Kontrol yok. Console.WriteLine(ogr.Yas); // -5 Bu yaklaşımın sorunları: Kontrol Kaybı: Yas alanına negatif bir değer atanmasını engelleyemeyiz. Veri üzerinde hiçbir doğrulama veya kısıtlama uygulayamayız. Nesnenin durumu kolayca geçersiz hale gelebilir. Esneklik Kaybı: Gelecekte Yas alanının değerinin nasıl hesaplandığını veya saklandığını değiştirmek istersek (örn. doğum tarihinden hesaplamak, veritabanından okumak), bu alanı kullanan tüm kodları değiştirmemiz gerekir. Çünkü dış kod doğrudan alana bağımlıdır. Kapsülleme İhlali: Nesnenin iç yapısı (alanları) dışarıya tamamen açık hale gelir. Bu, “information hiding” (bilgi gizleme) prensibine aykırıdır. Çözüm: Özellikler (Properties) Özellikler, bu sorunları çözmek için tasarlanmıştır. Dışarıdan bakıldığında alan gibi kullanılırlar ( nesne.OzellikAdi ), ancak aslında arka planda çalışan özel metotlardır (get ve set erişimcileri). Bu metotlar, alanın değerine erişirken veya onu değiştirirken ek mantık çalıştırmamıza olanak tanır. Bölüm 1: Özelliklerin Temelleri ve Söz Dizimi 1.1. Tanım: Özellikler, bir sınıfın veya yapının (struct) üyesidir ve özel alanlara (backing fields) kontrollü erişim sağlamak için kullanılırlar. get ve set anahtar kelimeleriyle tanımlanan erişimci blokları içerirler. 1.2. Tam Özellik Söz Dizimi (Explicit Property Syntax): Bu, bir özelliğin özel bir alanla (backing field) birlikte açıkça tanımlandığı yöntemdir. private T backingField; // Özel destek alanı (genellikle private) [erişim_belirleyici] T PropertyName // Özellik tanımı (PascalCase) { // 'get' erişimcisi: Özelliğin değerini okumak için çağrılır [erişim_belirleyici] get { // Okuma mantığı (genellikle alanın değerini döndürür) // Ek mantık eklenebilir (örn. loglama, hesaplama) return _backingField; } // 'set' erişimcisi: Özelliğe değer atamak için çağrılır [erişim_belirleyici] set { // Yazma mantığı (genellikle alana değer atar) // Atanan değere 'value' anahtar kelimesi ile erişilir (türü T ile aynıdır) // Doğrulama, olay tetikleme gibi ek mantıklar eklenebilir _backingField = value; } } _backingField: Özelliğin gerçek değerini saklayan özel alandır. İsimlendirme kuralı olarak genellikle alt çizgi () ile başlar ve camelCase kullanılır. PropertyName: Özelliğin dışarıdan erişilecek adıdır (PascalCase). T: Özelliğin (ve genellikle destek alanının) veri türüdür. get Bloğu: Özellik okunduğunda çalışır ( Console.WriteLine(nesne.PropertyName); gibi). return ifadesiyle özelliğin değerini döndürmelidir. set Bloğu: Özelliğe değer atandığında çalışır ( nesne.PropertyName = yeniDeger; gibi). Atanan yeniDeger, set bloğu içinde value anahtar kelimesiyle erişilebilir durumdadır. Bu blok içinde genellikle _backingField = value; ataması yapılır, ancak öncesinde veya sonrasında ek mantıklar (doğrulama, olay tetikleme vb.) eklenebilir. Erişim Belirleyiciler (Accessor Accessibility): get ve set erişimcileri, özelliğin kendisinden daha kısıtlayıcı erişim belirleyicilere sahip olabilir. Örneğin, özellik public iken set erişimcisi private yapılabilir ( public decimal Bakiye { get; private set; } ). Bu, özelliğin dışarıdan okunabilmesini ama sadece sınıf içinden değiştirilebilmesini sağlar. Örnek (Öğrenci Yaşı Kontrolü): public class OgrenciProperty { private string _ad; private int _yas; // Özel destek alanı public string Ad { get { return _ad; } set { _ad = value; } // Basit get/set } public int Yas // Kontrollü özellik { get { // Okuma sırasında ek mantık (nadiren gerekir ama mümkün) Console.WriteLine($"{_ad} için yaş okunuyor..."); return _yas; } set { // Yazma sırasında doğrulama mantığı Console.WriteLine($"{_ad} için yaş atanıyor: {value}"); if (value >= 6 && value

Apr 9, 2025 - 11:27
 0
C# ve .NET [7]

Giriş: Veriye Kontrollü Erişim İhtiyacı ve Kapsülleme

Nesne Yönelimli Programlamanın temel hedeflerinden biri, bir nesnenin iç durumunu (verilerini) korumak ve dış dünyadan gelen doğrudan, kontrolsüz erişimi engellemektir. Bu prensibe Kapsülleme (Encapsulation) denir. Kapsülleme, ilgili verileri (alanları) ve bu veriler üzerinde çalışan metotları bir sınıf içinde bir araya getirmek ve genellikle verilere erişimi kısıtlayıp (örneğin private yaparak), bu verilere sadece sınıfın kendi metotları veya kontrollü arayüzleri (özellikler gibi) üzerinden erişilmesini sağlamaktır.

Neden Doğrudan Alan Erişimi Kötü Bir Fikirdir?

Eğer bir sınıfın alanlarını public yaparsak:

public class YanlisOgrenci
{
public string Ad; // Public alan - KÖTÜ!
public int Yas; // Public alan - KÖTÜ!
}
// Kullanım:
YanlisOgrenci ogr = new YanlisOgrenci();
ogr.Ad = "Ali";
ogr.Yas = -5; // Geçersiz bir değer doğrudan atanabiliyor! Kontrol yok.
Console.WriteLine(ogr.Yas); // -5
Bu yaklaşımın sorunları:

Kontrol Kaybı: Yas alanına negatif bir değer atanmasını engelleyemeyiz. Veri üzerinde hiçbir doğrulama veya kısıtlama uygulayamayız. Nesnenin durumu kolayca geçersiz hale gelebilir.
Esneklik Kaybı: Gelecekte Yas alanının değerinin nasıl hesaplandığını veya saklandığını değiştirmek istersek (örn. doğum tarihinden hesaplamak, veritabanından okumak), bu alanı kullanan tüm kodları değiştirmemiz gerekir. Çünkü dış kod doğrudan alana bağımlıdır.
Kapsülleme İhlali: Nesnenin iç yapısı (alanları) dışarıya tamamen açık hale gelir. Bu, “information hiding” (bilgi gizleme) prensibine aykırıdır.
Çözüm: Özellikler (Properties)

Özellikler, bu sorunları çözmek için tasarlanmıştır. Dışarıdan bakıldığında alan gibi kullanılırlar ( nesne.OzellikAdi ), ancak aslında arka planda çalışan özel metotlardır (get ve set erişimcileri). Bu metotlar, alanın değerine erişirken veya onu değiştirirken ek mantık çalıştırmamıza olanak tanır.

Bölüm 1: Özelliklerin Temelleri ve Söz Dizimi

1.1. Tanım:

Özellikler, bir sınıfın veya yapının (struct) üyesidir ve özel alanlara (backing fields) kontrollü erişim sağlamak için kullanılırlar. get ve set anahtar kelimeleriyle tanımlanan erişimci blokları içerirler.

1.2. Tam Özellik Söz Dizimi (Explicit Property Syntax):

Bu, bir özelliğin özel bir alanla (backing field) birlikte açıkça tanımlandığı yöntemdir.

private T backingField; // Özel destek alanı (genellikle private)
[erişim_belirleyici] T PropertyName // Özellik tanımı (PascalCase)
{
// 'get' erişimcisi: Özelliğin değerini okumak için çağrılır
[erişim_belirleyici] get
{
// Okuma mantığı (genellikle alanın değerini döndürür)
// Ek mantık eklenebilir (örn. loglama, hesaplama)
return _backingField;
}
// 'set' erişimcisi: Özelliğe değer atamak için çağrılır
[erişim_belirleyici] set
{
// Yazma mantığı (genellikle alana değer atar)
// Atanan değere 'value' anahtar kelimesi ile erişilir (türü T ile aynıdır)
// Doğrulama, olay tetikleme gibi ek mantıklar eklenebilir
_backingField = value;
}
}
_backingField: Özelliğin gerçek değerini saklayan özel alandır. İsimlendirme kuralı olarak genellikle alt çizgi (
) ile başlar ve camelCase kullanılır.
PropertyName: Özelliğin dışarıdan erişilecek adıdır (PascalCase).
T: Özelliğin (ve genellikle destek alanının) veri türüdür.
get Bloğu: Özellik okunduğunda çalışır ( Console.WriteLine(nesne.PropertyName); gibi). return ifadesiyle özelliğin değerini döndürmelidir.
set Bloğu: Özelliğe değer atandığında çalışır ( nesne.PropertyName = yeniDeger; gibi). Atanan yeniDeger, set bloğu içinde value anahtar kelimesiyle erişilebilir durumdadır. Bu blok içinde genellikle _backingField = value; ataması yapılır, ancak öncesinde veya sonrasında ek mantıklar (doğrulama, olay tetikleme vb.) eklenebilir.
Erişim Belirleyiciler (Accessor Accessibility): get ve set erişimcileri, özelliğin kendisinden daha kısıtlayıcı erişim belirleyicilere sahip olabilir. Örneğin, özellik public iken set erişimcisi private yapılabilir ( public decimal Bakiye { get; private set; } ). Bu, özelliğin dışarıdan okunabilmesini ama sadece sınıf içinden değiştirilebilmesini sağlar.
Örnek (Öğrenci Yaşı Kontrolü):

public class OgrenciProperty
{
private string _ad;
private int _yas; // Özel destek alanı
public string Ad
{
get { return _ad; }
set { _ad = value; } // Basit get/set
}
public int Yas // Kontrollü özellik
{
get
{
// Okuma sırasında ek mantık (nadiren gerekir ama mümkün)
Console.WriteLine($"{_ad} için yaş okunuyor...");
return _yas;
}
set
{
// Yazma sırasında doğrulama mantığı
Console.WriteLine($"{_ad} için yaş atanıyor: {value}");
if (value >= 6 && value <= 120) // Geçerli yaş aralığı
{
_yas = value; // Değeri alana ata
}
else
{
// Geçersiz değeri atama veya hata fırlat
Console.WriteLine($"Geçersiz yaş değeri: {value}. Atama yapılmadı.");
// throw new ArgumentOutOfRangeException("Yas", "Yaş 6 ile 120 arasında olmalıdır.");
}
}
}
// Yapıcı
public OgrenciProperty(string ad, int yas)
{
_ad = ad;
Yas = yas; // Doğrudan alana değil, set erişimcisine atama yapar (validasyon çalışır!)
}
}
// Kullanım:
OgrenciProperty ogr1 = new OgrenciProperty("Ayşe", 20); // Yapıcıdaki Yas = yas; set erişimcisini tetikler.
Console.WriteLine(ogr1.Yas); // get erişimcisi çalışır.
ogr1.Yas = 21; // set erişimcisi çalışır (geçerli değer).
Console.WriteLine(ogr1.Yas); // 21
ogr1.Yas = 5; // set erişimcisi çalışır (geçersiz değer).
Console.WriteLine(ogr1.Yas); // Hala 21 (geçersiz değer atanmadı).
Bölüm 2: Otomatik Uygulanan Özellikler (Auto-Implemented Properties)

Çoğu zaman, get ve set erişimcileri içinde özel bir mantığa ihtiyaç duyulmaz; sadece değeri alıp ayarlamak yeterlidir. Bu yaygın senaryo için C# 3.0 ve sonrası, otomatik uygulanan özellikler adı verilen çok daha kısa bir söz dizimi sunar.

Sözdizimi:

[erişim_belirleyici] T PropertyName { [erişim_belirleyici] get; [erişim_belirleyici] set; }
Özellik, get; ve set; (veya sadece biri) ile tanımlanır. Gövdeleri ({…}) yazılmaz.
Derleyici, bu söz dizimini gördüğünde arka planda otomatik olarak (anonim, erişilemeyen) private bir destek alanı (backing field) oluşturur. get erişimcisi bu gizli alanın değerini döndürür, set erişimcisi ise value’yu bu gizli alana atar.
Bu, tam özellik söz diziminin sıkıcı ve tekrarlı kısımlarını ortadan kaldırır.
Örnek:

public class ArabaOtomatik
{
// Otomatik Uygulanan Özellikler
public string Marka { get; set; } // Public get, public set (Arka planda private alan var)
public string Model { get; set; }
public int Yil { get; } // Public get, set yok (Salt okunur - sadece yapıcıda atanabilir)
public double MotorHacmi { get; private set; } // Public get, private set (Sınıf içinden atanabilir)
public int KapiSayisi { get; init; } // Public get, init set (C# 9+ - Sadece yapıcı veya nesne başlatıcıda atanabilir)
public ArabaOtomatik(int yil, double motorHacmi, int kapiSayisi = 4)
{
// Salt okunur (get-only) otomatik özellik yapıcıda atanabilir
this.Yil = yil;
// Private set'li özellik yapıcıda atanabilir
this.MotorHacmi = motorHacmi;
// init-only özellik yapıcıda atanabilir
this.KapiSayisi = kapiSayisi;
}
public void MotorGuncelle(double yeniHacim)
{
// Private set'e sınıf içinden erişilebilir
this.MotorHacmi = yeniHacim;
}
}
// Kullanım:
ArabaOtomatik araba1 = new ArabaOtomatik(2023, 1.6, 5) // Yapıcı çağrılır
{
Marka = "Volkswagen", // Public set erişimcisi kullanılır
Model = "Golf", // Public set erişimcisi kullanılır
// KapiSayisi = 3 // init olduğu için nesne başlatıcıda da atanabilir (yapıcıda atanmamış olsaydı)
};
Console.WriteLine(araba1.Marka); // Public get
// araba1.Yil = 2024; // Hata! Yil salt okunur (set yok).
// araba1.MotorHacmi = 1.8; // Hata! MotorHacmi'nin set'i private.
araba1.MotorGuncelle(1.8); // Geçerli (sınıf içi metottan private set'e erişim)
// araba1.KapiSayisi = 2; // Hata! init sadece başlangıçta atanabilir.
Kural: Eğer get veya set içinde özel bir mantık (doğrulama, hesaplama, olay tetikleme vb.) yoksa, her zaman otomatik uygulanan özellikleri tercih edin. Kodunuz daha kısa ve temiz olur. Özel mantık gerektiğinde tam özellik söz dizimine geçebilirsiniz.

Bölüm 3: Özellik Türleri

Erişimcilerin varlığına ve erişim düzeylerine göre farklı özellik türleri ortaya çıkar:

Okuma-Yazma (Read-Write): Hem get hem de set erişimcisi vardır ve ikisi de erişilebilirdir (genellikle ikisi de public). Bu en yaygın türdür.
public string AdSoyad { get; set; }
Salt Okunur (Read-Only): Sadece get erişimcisi vardır veya set erişimcisi private (veya daha kısıtlı) yapılmıştır. Değeri genellikle yapıcıda (constructor) veya nesne başlatıcıda (init ile) ayarlanır ve daha sonra dışarıdan değiştirilemez. Nesnenin değişmezliğini (immutability) sağlamaya yardımcı olur.
public int KullaniciId { get; } // Sadece get var public DateTime OlusturmaTarihi { get; private set; } // Dışarıdan okunur, içeriden yazılır public Guid BenzersizAnahtar { get; init; } // Başlangıçta atanır, sonra değişmez
Salt Yazılır (Write-Only): Sadece set erişimcisi vardır. Değeri okunamaz, sadece ayarlanabilir. Çok nadiren kullanılırlar, çünkü genellikle bir şeyin değerini ayarladıktan sonra okuyabilmek istenir. Hassas verileri (şifre gibi) ayarlamak için kullanılabilirler ancak bu durumda bile genellikle okunamaması yerine başka güvenlik önlemleri tercih edilir.
private string _gizliVeri; public string AyarlanacakVeri { set { _gizliVeri = Sifrele(value); } // Sadece set var }
Bölüm 4: İfade Gövdeli Üyeler (Expression-Bodied Members — C# 6+)

Eğer bir özelliğin get veya set erişimcisi sadece tek bir ifade içeriyorsa (genellikle bir değer döndürme veya atama), C# 6 ve sonrası daha kısa bir söz dizimi sunar: ifade gövdeli üyeler. => (lambda oku) kullanılır ve {} ile return (get için) veya atama (set için) kaldırılır.

Sözdizimi:

// get için:
public T PropertyName => _backingField; // return _backingField; ile aynı
public T PropertyName => SomeCalculation();
// set için (C# 7.0+):
public T PropertyName
{
get => _backingField;
set => _backingField = value; // Tek satırlık set bloğu
}
// VEYA
public T PropertyName
{
get => _backingField;
set => PerformValidationAndSet(value); // Başka bir metodu çağırabilir
}
// Sadece get olan salt okunur özellikler için çok yaygındır:
public string TamAd => $"{_ad} {_soyad}"; // Hesaplanan özellik
public bool GecerliMi => _yas > 0;
Örnek:

public class Dikdortgen
{
public double Genislik { get; set; }
public double Yukseklik { get; set; }
// İfade gövdeli salt okunur özellik (hesaplanan)
public double Alan => Genislik * Yukseklik;
// İfade gövdeli get ve set (C# 7.0+)
private string _renk = "Mavi";
public string Renk
{
get => _renk;
set => _renk = !string.IsNullOrEmpty(value) ? value : "Bilinmiyor"; // Basit doğrulama
}
public Dikdortgen(double g, double y) { Genislik = g; Yukseklik = y; }
}
// Kullanım:
Dikdortgen d = new Dikdortgen(10, 5);
Console.WriteLine($"Alan: {d.Alan}"); // Alan: 50
d.Renk = "";
Console.WriteLine($"Renk: {d.Renk}"); // Renk: Bilinmiyor
İfade gövdeli üyeler, özellikle basit erişimciler ve hesaplanan özellikler için kodu önemli ölçüde kısaltır ve okunabilirliği artırır.

Bölüm 5: Özellikler ve Kapsülleme İlişkisi

Özelliklerin temel amacı kapsüllemeyi sağlamaktır:

Bilgi Gizleme (Information Hiding): Sınıfın iç uygulama detayları (özel alanlar) dış dünyadan gizlenir. Dış kod sadece public arayüzle (özellikler, metotlar) etkileşime girer.
Kontrollü Erişim: Özellikler, verilere erişim ve değişiklik üzerinde tam kontrol sağlar. get ve set blokları içine mantık ekleyerek:
Doğrulama (Validation): Atanmaya çalışılan değerin geçerli olup olmadığını kontrol edebiliriz (örneğin yaşın negatif olmaması).
Hesaplama (Computation): Özellik değeri okunduğunda veya yazıldığında başka hesaplamalar yapabiliriz (örn. TamAd özelliğinin _ad ve _soyad alanlarından hesaplanması).
Yan Etkiler (Side Effects): Özellik değeri değiştiğinde başka olayları tetikleyebiliriz (örn. bir kullanıcı arayüzünü güncellemek, log kaydı oluşturmak, bir olayı fırlatmak).
Esneklik ve Bakım Kolaylığı: Özelliğin dış arayüzü (public string Ad { get; set; }) aynı kalırken, iç uygulamasını (arka plandaki alan, get/set mantığı) daha sonra değiştirebiliriz. Bu değişikliği yapan sınıfı kullanan diğer kodları kırmak zorunda kalmayız. Örneğin, başlangıçta bir alanı doğrudan döndüren bir özellik, daha sonra değeri bir veritabanından okuyacak veya karmaşık bir hesaplama yapacak şekilde değiştirilebilir.
Örnek (Yan Etki):

public class SicaklikSensoru
{
private double _kelvin;
public event EventHandler? SicaklikDegisti; // Olay tanımı
public double Celsius
{
get => _kelvin - 273.15;
set
{
double yeniKelvin = value + 273.15;
if (_kelvin != yeniKelvin)
{
_kelvin = yeniKelvin;
// Sıcaklık değiştiğinde olayı tetikle (yan etki)
OnSicaklikDegisti();
}
}
}
public double Fahrenheit
{
get => Celsius * 9 / 5 + 32;
set => Celsius = (value - 32) * 5 / 9; // Celsius'un set'ini kullanır
}
public double Kelvin
{
get => _kelvin;
set {
if (_kelvin != value) {
_kelvin = value;
OnSicaklikDegisti();
}
}
}
protected virtual void OnSicaklikDegisti()
{
SicaklikDegisti?.Invoke(this, EventArgs.Empty); // Olayı fırlat
Console.WriteLine($"Sıcaklık değişti: {Celsius:F1}°C / {Fahrenheit:F1}°F");
}
}
// Kullanım:
SicaklikSensoru sensor = new SicaklikSensoru();
// Olay dinleyicisi ekle
sensor.SicaklikDegisti += (sender, args) => Console.WriteLine(">> Olay yakalandı!");
sensor.Celsius = 25; // set tetiklenir, olay fırlatılır
sensor.Fahrenheit = 77; // Önce Fahrenheit set, sonra Celsius set tetiklenir (değer aynıysa olay fırlamaz)
sensor.Kelvin = 300.15; // Kelvin set, olay fırlatılır
Bölüm 6: Alanlar (Fields) vs. Özellikler (Properties)

Ne zaman alan, ne zaman özellik kullanmalıyız?

Alanlar (private string _name;):
Genellikle private olmalıdır.
Sınıfın iç durumunu depolamak için kullanılır.
Dışarıya doğrudan açılmamalıdır.
Performans açısından özelliğe göre çok küçük bir avantajı olabilir (metot çağrı yükü yoktur), ancak bu modern .NET’te genellikle ihmal edilebilir ve kapsüllemenin faydaları çok daha ağır basar.
Özellikler (public string Name { get; set; }):
Genellikle public (veya protected/internal) olmalıdır.
Sınıfın dış arayüzünü oluşturur.
Özel alanlara kontrollü erişim sağlar.
Doğrulama, hesaplama, olay tetikleme gibi ek mantık eklemeye olanak tanır.
Otomatik uygulanan özellikler, basit durumlar için alan tanımlama ihtiyacını ortadan kaldırır.
Kural: Sınıfın dışarıdan erişilmesi veya değiştirilmesi gereken verileri için her zaman özellikleri kullanın. Özel alanları sadece sınıfın içsel durumu için ve genellikle bu özelliklerin destek alanı olarak kullanın.

Bölüm 7: Sonuç — Kapsüllemenin Zarif Yolu

C# Özellikleri (get/set erişimcileriyle), Nesne Yönelimli Programlamanın temel prensiplerinden olan Kapsülleme’yi uygulamak için vazgeçilmez bir araçtır. Özel alanlara doğrudan erişimi engelleyerek ve verilere kontrollü bir arayüz sunarak kodun daha güvenli, daha esnek ve daha bakımı kolay olmasını sağlarlar.

Tam özellik söz dizimi, get ve set işlemleri sırasında doğrulama, hesaplama veya yan etki gibi özel mantıklar eklememize olanak tanırken, otomatik uygulanan özellikler basit veri erişimi senaryoları için çok daha kısa ve temiz bir alternatif sunar. Salt okunur veya kontrollü yazılabilir özellikler tanımlama yeteneği, nesnenin durumunun istenmeyen şekillerde değiştirilmesini engeller. C# 6 ve sonrasında gelen ifade gövdeli üyeler ise basit özellik tanımlarını daha da kısaltır.

Özellikler, C#’ta sınıfları ve yapıları tasarlarken verilerle etkileşim kurmanın standart ve en iyi yoludur. Alanları private tutmak ve bunlara erişimi özellikler üzerinden sağlamak, OOP’nin temelini oluşturan sağlam ve sürdürülebilir kod yazma pratiğidir. Bu mekanizmaya hakim olmak, etkili ve profesyonel C# kodu geliştirmek için esastır.

Abdulkadir Güngör - Kişisel WebSite
Abdulkadir Güngör - Kişisel WebSite
Abdulkadir Güngör - Özgeçmiş
Github
Github
Linkedin