C# Erişim Belirleyicilerini Anlamak
Bu makalede, C#'daki türlerin, yöntemlerin ve değişkenlerin görünürlüğünü ve erişilebilirliğini tanımlayan C# erişim belirleyicilerine dalacağız. Tim Corey, 'C# Access Modifiers (beyond public and private) - what they are, how to use them, and best practices' adlı videosunda çeşitli erişim belirleyicilerini açıklayarak bunların bir konsol uygulamasındaki pratik kullanımını göstermektedir.
Bu makale, Tim'in ele aldığı konuları ve anlamanızı artırmak için kod örneklerini açıklayacaktır. Sağlanan zaman damgaları, daha pratik bir deneyim için video ile eşlik etmenizi sağlar.
Erişim Belirleyicileri Nedir?
Giriş
Tim Corey, erişim belirleyicilerini tanıtarak C#'ta kimin bir kaynağı görebileceğini ve kullanabileceğini belirlediklerini açıklar. Yaygın olarak kullanılan public ve private belirleyicileri ile aşina olsak da, Tim altı farklı erişim belirleyicisi ve kullanım durumlarını inceler.
Demo Uygulaması Açıklandı
Tim, çeşitli erişim belirleyicilerinin nasıl çalıştığını göstermek için basit bir uygulama hazırlar. Uygulama, .NET framework'te hem bir konsol kullanıcı arayüzü hem de bir demo kütüphanesi içerir.
Proje Yapısı:
- Konsol UI: Erişim belirleyicilerini test etmek için bir konsol uygulaması.
- Demo Kütüphanesi: Farklı erişim belirleyicilerin gösterildiği bir sınıf kütüphanesi.
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}1. Private
Nedir:
Private belirleyici, erişimi yalnızca tanımlandığı sınıf içinde sınırlı tutar.
Kod Örneği:
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}Açıklama: PrivateDemo yöntemi, yalnızca AccessDemo sınıfı içinde erişilebilir. Videoda Tim, aynı proje içindeyken bile sınıf dışından erişilemeyeceğini gösterir.
En İyi Uygulama: Sınıfınızın iç işleyişine erişimi sınırlamak istediğinizde private kullanın, böylece uygulamanızın diğer bölümlerinden doğrudan değiştirilemez.
2. Internal
Nedir:
Internal belirleyici, yöntem ya da özelliğe yalnızca aynı derleme (proje) içinde erişim sağlar. Bu, aynı proje içindeki tüm sınıfları içerdiğinden private erişim belirleyicisinden daha geniştir.
Kod Örneği:
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}Açıklama: InternalDemo yöntemi, aynı derlemeden herhangi bir sınıf tarafından erişilebilir, ancak diğer derlemelerden erişilemez. Videoda, Tim, internal'ın aynı proje içindeki erişime izin verdiğini ancak dıştan erişimi reddettiğini gösterir.
En İyi Uygulama: Sadece mevcut derleme içinde kullanılmak üzere tasarlanmış, yardımcı işlevler veya harici projelere açılmaması gereken özellikler için internal kullanın.
3. Public
Nedir:
Public belirleyici, yöntem ya da özelliğe diğer tüm sınıf veya derlemelerden erişim sağlar. Bu, en geniş erişim seviyesidir.
Kod Örneği:
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}Açıklama: PublicDemo yöntemi, aynı derlemedeki veya diğer derlemelerdeki diğer sınıflar da dahil olmak üzere her yerden erişilebilir. Tim, public'in en yaygın erişim belirleyicisi olduğunu, özellikle kütüphanelerde yöntemlerin dışarıya açılması sırasında gösterir.
En İyi Uygulama: API uç noktaları veya yaygın kullanılan yardımcılar gibi diğer uygulama parçaları veya dış projeler tarafından erişilmesi gereken yöntemler ve özellikler için public kullanın.
4. Korunmuş
Nedir:
Protected belirleyicisi, yöntem veya özelliğe tanımlandığı sınıf içerisinde ve türetilmiş sınıflarda (kalıtımda) erişim sağlar. Bu belirleyici, özellikle kalıtım durumlarında nesne yönelimli programlama için kullanışlıdır.
Kod Örneği:
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}Açıklama: ProtectedDemo yöntemi, AccessDemo sınıfından ve ondan türeyen herhangi bir sınıftan erişilebilir. Tim, protected'ın daha az yaygın olduğunu ancak kalıtımla çalışırken çok faydalı olduğunu açıklar.
En İyi Uygulama: Türetilmiş sınıfların belirli yöntemlere veya özelliklere erişimini sağlamak istediğiniz, ancak sınıf hiyerarşisinin dışına erişim istemediğiniz durumlarda protected kullanın.
5. Özel Korunmuş
Nedir:
Private protected belirleyicisi, özel ve korunmuş kurallarını birleştirir. Bu, yöntemler veya özellikler için tanımlayıcı sınıf içindeki ve aynı derleme içindeki türetilmiş sınıflarda erişimi sınırlar. Bu, koruma tabanlı erişim kontrolü için protected ile karşılaştırıldığında daha sıkı bir sınır ve daha yüksek bir koruma seviyesi sunar.
Kod Örneği:
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}Açıklama: PrivateProtectedDemo yöntemi, DerivedClass içinde erişilebilir çünkü AccessDemo'dan türetilmiştir ve aynı derlemede bulunmaktadır. Ancak, UnrelatedClass içinde erişilemez, çünkü bu sınıf AccessDemo'dan türetilmemiştir.
En İyi Uygulama: Aynı derleme içinde kalıtım erişimini sıkı bir biçimde kontrol etmeniz gerektiğinde private protected erişim belirleyiciyi dikkatli kullanın. Bu, özellikle yöntemlerin veya özelliklerin derlemeler arasında açılması durumu kapsüllemeyi tehlikeye atabileceği zamanlarda faydalıdır.
6. Korunmuş İçsel
Nedir:
Korunmuş içsel belirleyicisi, korunmuş ve içsel erişim belirleyici seviyelerini birleştirir. Bu, aynı derlemeden veya türetilmiş sınıflardan erişime izin verir, hatta başka bir derlemede olsalar bile.
Kod Örneği:
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}Açıklama: ProtectedInternalDemo yöntemi, aynı derleme içinde ve ayrıca şu türeyen sınıflardan erişilebilir, derleme ne olursa olsun.
En İyi Uygulama: Hem türetilmiş sınıflara (diğer derlemelerde) hem de aynı derleme içindeki sınıflara bir yöntemi açmak istediğinizde protected internal kullanın, ancak herkese değil.
Neden Her Şeyi Kamuya Açmak Değil?
Tim Corey, erişim belirleyicilerinin kullanımının önemini ve her şeyin neden yalnızca public olmaması gerektiğini açıklar. Her şeyi public yapmak uygun gibi görünse de, veri ihlalleri, hatalar ve geliştiriciliğin kafa karıştırıcı olması gibi ciddi riskleri de beraberinde getirir. Erişim belirleyicileri, bilgiyi güvence altına almak, istenmeyen herkese açık erişimi önlemek ve kod tabanlarında netlik sağlamak için oluşturulmuştur.
1. Özel Bilgilerin Korunması
Tim, Sosyal Güvenlik Numaraları (SSN) veya kredi kartı numaraları gibi hassas bilgilerin neden kamuya açılmaması gerektiğini tartışır. Halk erişimi nedeniyle veri maruziyeti olan bir 'kötü sınıf' örneği gösterir:
Kötü Örnek:
public class User
{
public string SSN; // Anyone can access and modify it directly
}public class User
{
public string SSN; // Anyone can access and modify it directly
}İyi Örnek:
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}2. Özel Yöntemlerin Güvence Altına Alınması
Başlangıç: 35:11\ Tim, özel yöntemlerin, doğrudan erişilebilir olmaması gereken davranışların kapsüllenmesine yardım ettiğini açıklar. Bir DeleteUser yöntem örneğini, çalışan ayrılık süreci gibi daha büyük bir sürecin parçası olarak kullanır.
Kötü Örnek:
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}İyi Örnek:
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}3. Hataların Önlenmesi
Erişim belirleyicileri, verilerin uygun doğrulama ile ayarlanması veya alınması konusunda hataları önler. Tim, bir Age özelliği içeren bir örnekle bunu resmeder.
Kötü Örnek:
public class Person
{
public int Age; // Can be directly set to an invalid value
}public class Person
{
public int Age; // Can be directly set to an invalid value
}İyi Örnek:
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}4. Kafa Karışıklığının Azaltılması ve Netliğin Artırılması
Erişim belirleyicilerinin doğru kullanımı, yalnızca gerekli olanın açığa çıkarılması ile geliştirmeyi basitleştirir, kafa karışıklığını önler. Örneğin, binlerce yöntemi olan bir uygulamada, yalnızca kamuya açık olanları açığa çıkararak geliştiricilerin yalnızca ilgili seçenekleri görmesini sağlamak.
Örnek:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}5. Daha Büyük Uygulamalar veya Kütüphanelerde Faydaları
Büyük ölçekli projeler için, Tim, erişim belirleyicilerinin doğru kullanımının, bir kütüphanenin yalnızca gerekli bölümlerinin ifşa edilmesini sağlayarak, kütüphaneyi kullanan geliştiriciler için bilişsel yükü azalttığını açıklar.
Örnek:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}Bu erişim belirleyicilerini doğru kullanarak hem kendi işinizi hem de kodunuzu okuyan bir sonraki kişinin işini kolaylaştırırsınız.
Sonuç
Tim Corey, C# erişim belirleyicilerini ustaca kullanmaya yönelik net ve pratik bir rehber sunarak, bunları nasıl etkili bir şekilde kullanabileceğinizi ve güvenli, sürdürülebilir ve profesyonel uygulamalar oluşturabileceğinizi gösteriyor. Onun detaylı açıklamaları ve gerçek dünya örnekleri, bu konuyu tüm seviyelerde geliştiriciler için erişilebilir kılıyor.
Daha derin içgörüler ve bu kavramların aksiyonlarını görmek için Tim'in tam videosunu izlemeyi ve C# ve diğer programlama konularına yönelik değerli içeriklerle dolu kanalını keşfetmeyi unutmayın. Geliştirme becerilerinizi geliştirmeye kararlı olan herkes için ziyaret edilmesi gereken bir kaynak!

