13 Mart 2009 Cuma

Erişim Belirleyiciler / Access Modifiers (C#)

Tüm tipler ve tip üyeleri birer erişilebilirlik seviyesine sahiptirler. Bu erişilebilirlik seviyeleri, ilgili tiplerin ya da üyelerin aynı assembly ya da farklı bir assembly içerisindeki kod bloklarından kullanılabilip kullanılamayacağını belirler. C# dilinde 4 adet erişim belirleyici ve 5 adet erişim modeli vardır. Tiplere ya da üyelere erişilebilirlik şu anahtar kelimeler ile belirlenir: public , private , protected , internal, protected internal
  • public bir tip ya da üye, aynı assembly içerisinden ya da kendisini refere eden başka bir assembly içerisinden erişilebilir, yani her yerden erişilebilir.
  • private bir tip ya da üye, sadece üyesi bulunduğu tipin (class ya da struct) içerisindeki kod bloklarından erişilip kullanılabilir.
  • protected bir tip ya da üye, üyesi bulunduğu tipin (class ya da struct) içerisindeki kod bloklarından ya da aynı tipten kalıtılmış diğer tiplerin içerisinden erişilebilir. Kalıtım farklı bir assembly üzerinden yapılmış olabilir. protected bir üyeye, üye ile aynı tipten kalıtılmış olmak şartı ile farklı bir assembly üzerindeki bir tipten de erişilebilir.
  • internal bir tip ya da üye, kendi yer aldığı assembly içerisinden erişilip kullanılabilir. Farklı bir assembly içerisinden erişim mümkün değildir.
  • protected internal bir tip ya da üye, kendi yer aldığı assembly içerisindeki kod bloklarından ya da üyesi bulunduğu tipten kalıtılmış olan (kalıtılmış tip farklı bir assembly içerisinde olabilir) diğer tiplerin içerisinden erişilebilir.
    protected internal erişim şekli protected ve internal erişim belirleyicilerinin aynı anda, yan yana kullanılmasından ibarettir, internal protected şeklinde de yazılabilir. internal bir üyeye erişebilecek olan kod blokları da, protected bir üyeye erişebilecek olan kod blokları da protected internal bir üyeye erişebilirler.

Erişim belirleyiciler ile ilgili yanlış bilinen ve doğru sanılan bazı bilgilere de değinmek istiyorum. Bu bilgileri aşağıda ele aldım ve doğrularını da yanlarında aktardım:
  • protected bir üyeye, sadece üyesi bulunduğu tipin içerisinden ve kalıtım ağacındaki bir alt tipin içerisinden erişilebilir. <-- YANLIŞ DOĞRU --> protected bir üye, kalıtım yolu ile aynı soyağacında yer alan tüm tiplerin içerisinden erişilebilir. Üyeyi kullanacak olduğumuz tip, direkt olarak üye ile aynı tipten değil de aynı soyağacındaki başka bir tipten kalıtılmış olabilir. Bu durum protected üyeyi kullanmamıza engel değildir.
  • internal bir tip ya da üye, tanımlandığı tipin içerisinden ya da tipin tanımlı olduğu namespace içerisinden erişilebilir. <-- YANLIŞ DOĞRU --> Bu durumun namespace ile alakası yoktur. internal bir tip ya da üye kendi yer aldığı assembly içerisindeki farklı bir namespace'ten de erişilebilir.
  • protected internal bir tip ya da üye, aynı namespace altında olup kalıtım ile ele alınmış tiplerin içerisinden erişilebilir. <-- YANLIŞ
    Bir üstteki maddede de belirtildiği gibi internal erişim belirleyicisinin namespace ile bir ilgilisi yoktur. O halde protected internal bir tip ya da üye, aynı assembly içerisinde olup kalıtım ile ele alınmış tiplerin içerisinden erişilebilir. <-- YİNE YANLIŞ DOĞRU --> protected internal bir tip ya da üye, internal olduğu için aynlı assembly içerisindeki her yerden erişilebilir, protected olduğu için de kalıtım yolu ile aynı soyağacında yer alan tiplerin içerisinden erişilebilir. Aynı soyağacında olan bu tipler aynı assembly içerisinde ya da farklı bir assembly içerisinde yer alabilir.
- Peki sadece aynı assembly içerisindeki aynı soyağacında olan tiplerin erişmesini istediğimiz bir üyenin erişim belirleyicisi ne olmalı?
- Üyeyi internal olarak tanımlamak aynı assembly içerisindeki herkese erişim imkanı sağlayacağı için işimizi görmez. Üyeyi protected yapmak soyağacı açısından işimizi görüyor gibi dursa da assembly'nin dışında ve aynı soyağacında olan tiplere de üyemizi açmamıza sebep olacaktır, dolayısı ile işimizi görmez. Üyenin protected internal olması da hem internal hem protected olmasından dolayı işimizi görmez.
Doğru çözüm yolu, üyeyi protected yapıp üyenin mensup olduğu tipi de internal yapmak olacaktır. Tip internal olduğu için farklı bir assembly içerisinden kullanılarak kalıtım uygulanamaz. Dışarıdan kalıtım yapılamayacağı garanti altına alındıktan sonra üyenin protected olması bizim için yeterli olacaktır. Çünkü sadece içeride kalıtım yapılabilir ve protected üye sadece kalıtım yolu ile ele alınabilir. Bu da bizi aynı assembly içerisindeki aynı soyağacında olan tiplerin erişebileceği bir üyeye götürür.

Tiplerin ya da üyelerin erişim belirleyicileri tanımlanmadığında default değerlerini alırlar. Üyeler için default erişim belirleyici, private erişim belirleyicisidir. namespace seviyesinde tanımladığımız tipler için default erişim belirleyici internal erişim belirleyicisidir.

ÖNEMLİ NOT: Eğer .NET Framework 1.1 ve Visual Studio 2003 kullanarak uygulama geliştirmeye devam eden bir programcı iseniz, C# 1.0 döneminde default erişim belirleyicinin public olarak belirlenmiş olduğunu unutmayınız.

namespace seviyesinde tanımlanan tipler, üyelere özel olan private ve protected erişim belirleyicilerini kullanamazlar. protected erişim belirleyicisi kullanılamadığından dolayı protected internal erişim modeli de kullanılamaz. namespace seviyesindeki bir tip sadece public ve internal erişim belirleyicileri ile tanımlanabilir.

Tiplerin içerisindeki üyeler, beş erişim modelini de kullanabilir. Tipler namespace seviyesinde sadece iki erişim belirleyici kullanabilirler fakat eğer bir tip, başka bir tipin içerisinde kodlanmış ise, aynı diğer üyeler gibi beş erişim modelini de kullanabilir.

- Yani bir class tanımlanırken, beş erişim modeli de kullanılabilir mi?
- Eğer ilgili class, namespace seviyesinde tanımlanmış ise sadece public ve internal olarak 2 erişim modelini kullanabilir, fakat inner-type olarak başka bir tipin içerisine yazılmış ise, artık o tipin üyesidir ve beş erişim modelini de kullanabilir.

Hiç yorum yok: