C Sharp Programlama Dili/Nitelikler
Nitelikler koda bir eleman hakkında ekstra bilgi eklemek için kullanılan ve elemanın bildiriminden hemen önce yazılan özel kodlardır. C#'ta hazır nitelikler olduğu gibi kendi niteliklerimizi de yazabiliriz. Şimdi isterseniz önce hazır niteliklerden başlayalım.
Hazır nitelikler
değiştirConditional niteliği
değiştirBu nitelik yalnızca metotlarla kullanılır. Önişlemci komutlarında gördüğümüz sembol programda varsa ilişkili metot çağrılır, nitelikteki sembol programda yoksa metot çağrılmaz. Bu nitelik System.Diagnostics isim alanında bulunur. Örnek program:
#define TURKCE
using System;
using System.Diagnostics;
class Deneme
{
[Conditional("TURKCE")]
static void Turkce()
{
Console.WriteLine("Bu program Türkçedir.");
}
[Conditional("ENGLISH")]
static void English()
{
Console.WriteLine("Bu program İngilizcedir.");
}
static void Main()
{
Turkce();
English();
}
}
Bu program ekrana programın Türkçe olduğunu yazacaktır. Yani program hata vermedi, yalnızca English() metodunun çalıştırılmasını engelledi. Çünkü ilgili sembol programda yoktu.
DllImport niteliği
değiştirBu nitelik bir metodun .Net ortamında geliştirilmediğini belirtmek için kullanılır. .Net kütüphanesini değil de Windows API'lerini kullanabilmek için bu nitelik gereklidir. Ayrıca ilgili metodun dışarıdan alındığını belirtmek için extern anahtar sözcüğünü kullanırız. Bu nitelik System.Runtime.InteropServices isim alanında bulunur.
DllImport niteliğini bir Windows API fonksiyonu olan MessageBox() üzerinde görebiliriz. Bu fonksiyonu C# programımızda kullanabilmek için DllImport niteliği ile belirtmeli, ayrıca extern anahtar sözcüğü ile de ayrı bir belirtim yapmalıyız. MessageBox Windows programlarında sıkça görebileceğimiz uyarı penceresi anlamına gelir ve üzerinde çeşitli uyarı metinlerinin olduğu bir uyarı penceresi çıkarır. Kullanıcı ekrandaki "Tamam" veya "İptal" gibi butonları tıklayabilir. Şimdi bunları kodsal olarak örnekleyelim.
using System;
using System.Runtime.InteropServices;
class Nitelikler
{
[DllImport("User32.dll")]
public static extern int MessageBox(int aile, string mesaj, string baslik, int tip);
static void Main()
{
MessageBox(0,"Bu bir uyarı mesajıdır","C#",1);
}
}
Gördüğünüz gibi kendi metodumuzu oluşturmuş gibi gözüküyoruz. Ancak aslında tek yaptığımız şey User32.dll dosyasından ilgili fonksiyonu alıp programımıza bir metotmuş gibi geçirmek. MessageBox() metodunun son parametresini 0-6 aralığında bir tam sayı yapıp değişik buton kombinasyonları elde edebilirsiniz.
Obsolote niteliği
değiştirBu nitelikle bir metodun çağrılması durumunda hata ya da uyarı verilmesi sağlanır. Önişlemci komutlarındaki #error ve #warning komutlarına benzer. İki kullanımı vardır:
[Obsolote("Uyarı mesajı")]
veya
[Obsolote("Uyarı mesajı", bool hata)]
Birinci örnekte eğer ilgili metot çağrılırsa derleyici uyarı verecektir. Yani program derlenecektir. İkinci örnekte ise eğer hata parametresi true ise program hata verecektir. Yani program derlenmeyecektir. Eğer ikinci örneğin hata parametresi false olursa birincisinden farkı kalmaz. İlk parametreler ise ekrana yazılan hata metnini belirlememizi sağlar. Obsolote niteliği System isim alanında bulunur.
AttributeUsage niteliği
değiştirBu nitelik ile kendi yazdığımız niteliklerin hangi elemanlarla kullanılabileceğini belirleriz. Parametre olarak AttributeTargets isimli enum nesnesi almaktadır. Bu enumun içerdiği sözcükler şunlardır: All, Assembly, Class, Constructor, Delegate, Enum, Event, Field, Interface, Method, Module, Parameter, Property, ReturnValue, Struct. Bu sözcüklerden tek anlamını çıkaramadığınız tahminimce Module'dür. Module sözcüğü isim alanlarını ifade eder. Örnek
[AttributeUsage(AttributeTargets.Method)]
Burada niteliğimizin yalnızca metotlara uygulanabileceğini belirttik. Şimdilik buna kafa takmanıza gerek yok. Az sonra kendi niteliklerimizi oluştururken AttributeUsage niteliğini uygulamalı olarak göreceksiniz.
Kendi niteliklerimizi oluşturmak
değiştirNitelikler aslında System.Attribute sınıfından türetilmiş sınıflardan başka bir şey değildir. O hâlde biz de kendi niteliklerimizi System.Attribute sınıfından türetme yaparak oluşturabiliriz. Örnek:
using System;
[AttributeUsage(AttributeTargets.Method)]
class KendiNiteligimiz:Attribute
{
public string Mesaj;
public KendiNiteligimiz(string mesaj)
{
Mesaj=mesaj;
}
}
class AnaProgram
{
[KendiNiteligimiz("Mesajımız")]
static void Metot(){}
static void Main(){}
}
Bu programda kendi niteliğimizi oluşturduk ve bu niteliğimizi bir metot üzerinde uyguladık. Niteliklerle ilgili diğer ilginç bir nokta ise niteliği kullanırken parametre verirken nitelikteki özelliklere değer verilebilmesidir. Örneğin:
[KendiNiteligimiz("Mesajımız",konu="C#",no=5.6)]
Burada niteliğimiz yalnızca bir parametre almasına rağmen diğer parametreler nitelikteki public özelliklere değer atamıştır. Bunu bir örnek üzerinde görelim:
using System;
[AttributeUsage(AttributeTargets.Method)]
class OzelNitelik:Attribute
{
public string Mesaj;
public int No;
public string Konu;
public OzelNitelik(string mesaj)
{
Mesaj=mesaj;
}
}
class Deneme
{
[OzelNitelik("Mesajımız",No=5,Konu="C#")]
static void Metot(){}
static void Main(){}
}
İlk parametre normal parametre olmalıdır. Diğerlerinden bazıları ya da tamamı olmayabilir. İlk parametre dışındakilerin kendi arasındaki sırası önemli değildir.
Bir elemana ilişkin nitelikleri yansıma yoluyla elde etmek için Attribute sınıfının static GetCustomAttribute() metodu kullanılabilir. Örnek:
using System;
class Yansima
{
static void Main()
{
Type t=typeof(Array);
Attribute[] dizi=Attribute.GetCustomAttributes(t);
foreach(Attribute a in dizi)
Console.WriteLine(a);
}
}
Benim bilgisayarımda program şu çıktıyı verdi:
System.SerializableAttribute System.Runtime.InteropServices.ComVisibleAttribute
Yani System.Array sınıfı bu iki niteliği kullanıyormuş. Yansıma yoluyla bir türün veya üye elemanın niteliklerini elde ettiğimizde aslında ilgili tür veya üye elemanın başındaki nitelikteki değerler kullanılarak ilgili nitelik sınıfı nesnesi oluşturulur. Geriye bu nesne döndürülür. Daha sonra bu nesne üzerinden niteliğin farklı kısımlarına ulaşabiliriz.