30 Temmuz 2012 Pazartesi

C# 2.0 - Generic Class Tanımlanması

C# 2,0 ile birlikte gelen güzel özelliklerden biri de Generic Class(Sınıf) tipler tanımlanabilmesidir. Kısaca bahsedersek Generic tanımlanan Class’ların bir örneğini oluşturmak istediğimizde, bu Class’ın işlevlerini hangi tip Class üzerinde gerçekleştireceğini belirtiriz. Ve bu işlevleri yerine getirecek olan Method’ların kabul edeceği tipler, Class’ın örneğini yaratırken belirlenmiş olur. Bu özellikten önce, bu şekildeki her tip için ayrı bir Class yazmak zorunda olurduk. Bu nedenle Generic Class tipleri daha az kod yazarak daha çok iş yapabilmemizi sağlayan güzel bir özelliktir. 

.NET içinde hazır gelen bir çok Generic Class vardır. Örneğin List<T> bunlardan en çok kullanılanıdır. Burada "< >" işaretleri arasında yazılan T, List Class’ının içinde T tipinde değerler tutacağını belirtir.List<T> gibi collection tipleri dışında IComparer veya IComparable gibi Interface’lerin IComparer<T>ve IComparable<T> gibi Generic olanlarıda vardır. 

Kullanımına bir kaç örnek vericek olursak; 

1- )
List<Rectangle> listRect = new List<Rectangle>();
Rectangle rect = new Rectangle(10,10,100,25);
listRect.Add(rect); // parametre olarak sadece Rectangle tipinde değeler alır.
2- )

public class ButtonComparer : IComparer<Button>
{
    #region IComparer<Button> Members

    public int Compare(Button x,Button y)
    {
        return x.Text.CompareTo(y.Text);
    }

    #endregion
}
Mevcut Generic Class’lar dışında bizde kendi Generic Class’larımızı yazarabilirizHatta Generic olarak belirteceğimiz Class tipinin belirli koşulları sağlamasını sağlayabiliriz. Örnek üzerinde gidecek olursak, şöyle bir Class yazalım.

public class MyGeneric<Tip>
{
    private Tip genericValue;

    public MyGeneric() { }

    public MyGeneric(Tip genericValue)
    {
        this.genericValue = genericValue;
    }

    public Tip GenericValue
    {
        get { return genericValue; }
        set { genericValue = value; }
    }

    public void writeGenericType()
    {
        Console.WriteLine(genericValue.GetType().ToString());
    }

    public void writeGenericValue()
    {
        Console.WriteLine(genericValue.ToString());
    }
}
Burada Tip olarak geçen bizim Generic tipimiz oluyor. Yani biz MyGeneric Class’ının bir örneğini yaratırken, tıpkı List<T> Class’ında oludğu gibi bu Class’ın generic tipini belirtiyoruz. Mesela biz MyGeneric<Button> temp; şeklinde bir tanımlama yaparsak, Class tanımı içinde ki Tip, Button olur. Örnekten devam edersek; 

MyGeneric<DateTime> temp = new MyGeneric<DateTime>(DateTime.Now);
temp.writeGenericType();
temp.writeGenericValue();

veya

MyGeneric<DateTime> temp = new MyGeneric<DateTime>();
temp.GenericValue = DateTime.Now;
temp.writeGenericType();
temp.writeGenericValue();
Burada writeGenericType() methodunu çalıştırdığımızda ekrana System.DateTime yazacaktır. Çünkü tanımımızda generic tip olarak DateTime verdik. Ayrıca writeGenericValue() method’uda o anki tarih ve saati yazacaktır. 

Koşullu Generic tipler

Kendi Generic Class’larımızı yazarken, bir önceki örnekte Tip ile belirttiğimiz generic tipin, belirli bir class’tan türemesi veya mutlaka parametresiz bir constructor’ı olması koşullarını belirtebiliriz. Böylece daha güçlü Generic Class tipleri yazma imkanımız olur. Bu özellik önceki versiyonlarda bulunmayan where keyword’ü ve mevcut new keyword’ünün başka bir kullanımını ile uygulanır. Bunu biraz önceki örnek kod üzerinde uygulayalım; 

public class MyClass
{
    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }
}

public class MyGeneric<Tip> where Tip : MyClass
{
    // Bazı kodlar
}
Buarada Tip ile belirtilen Generic Class tipinin MyClass’tan türeyen bir class olma koşulunu belirmiş olduk. Haliyle class’ımızın bu son hali ile, biraz önce DateTime verdiğimiz örnek hata atacaktır. Çünkü DateTime class’ı MyClass class’ından türememiştir. Burada bir class’tan türeme koşulu ile birlikte bir veya birden fazla Interface’i de implemente etme koşulu belirtebiliriz. 

public class MyClass
{
    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }
}

public interface MyInterface { }

public class MyGeneric<Tip> where Tip : MyClass,MyInterface
{
    // Bazı kodlar
}

//veya

public class MyGeneric<Tip> where Tip : MyClass,MyInterface,IClonable<Tip>
{
    // Bazı kodlar
}
Bu koşulların dışında biraz önce belirttiğim, Tip class’ının parametresiz constructor’ı olma koşulu ise şöyle kullanılıyor; 

public class MyGeneric<Tip> where Tip : new()
{
    // Bazı kodlar
}

// veya önceki örnekle birleştirirsek;

public class MyGeneric<Tip> where Tip : MyClass,MyInterface,new()
{
    // Bazı kodlar
}
Son duruma göre Tip ile belirteceğimiz class tipi, MyClass class’ından türemeli, MyInterface interface’ini implemente etmeli ve mutlaka parametresiz bir constructor’ ı olmalı. 

Konuyu ilk fark ettiğimde, parametresiz constructor olması koşulu gibi özellikle belli bir constructor’u olan generic tip koşulu tanımlamaya çalıştım ama olmadı :-). Oda olsa iyi olurmuş ama bu kadarı bile yeterince kolaylık sağlıyor. http://www.csharpnedir.com/articles/read/?id=566&title=C

Hiç yorum yok:

Yorum Gönder