Makale Özeti

.Net çatısı altında, bir dizi yada bir koleksiyon içerisindeki nesneleri sıralamanın yolunun, bu nesnelerin IComparable arayüzünü uygulamasından geçmesi gerektiğini geçen bölümde incelemiştik. Ancak sonucu yakından incelediğimizde, bu sıralamanın tek bir üye üzerinde ve tek yönlü olduğunu tespit etmiştik. Peki belirli bir sınıftan iki nesnenin karşılaştırılması sadece bu nesnelerin daha önce uygulamış oldukları IComparable.CompareTo() ya bağlı mı kalacak? Ya bu nesneler dizisi üzerinde farklı bir sıralama yapmamız gerekirse?

Makale

Karşılaştırılabilir/Sıralanabilir Nesneler 2 - IComparer

.Net çatısı altında, bir dizi yada bir koleksiyon içerisindeki nesneleri sıralamanın yolunun, bu nesnelerin IComparable arayüzünü uygulamasından geçmesi gerektiğini geçen bölümde incelemiştik. Ancak sonucu yakından incelediğimizde, bu sıralamanın tek bir üye üzerinde ve tek yönlü olduğunu tespit etmiştik. Yani sınıfımızın iki örneği üzerindeki karşılaştırma sadece Model değerleri göz önünde bulundurularak yapılır ve sıralama küçükten büyüğe doğru olacaktır.

Peki belirli bir sınıftan iki nesnenin karşılaştırılması sadece bu nesnelerin daha önce uygulamış oldukları IComparable.CompareTo() ya bağlı mı kalacak? Ya bu nesneler dizisi üzerinde farklı bir sıralama yapmamız gerekirse?

.Net çatısı bu probleme yine bir arayüzün uygulanmasıyla çözüm getiriyor: IComparer. Otomobil sınıfımıza yeniden bir göz atalım. Elimizde Model bilgisine göre, büyükten küçüğe sıralanabilir bir sınıf var.


/********************************************************************
*
* OTOMOBİL SINIFI
*
********************************************************************/


class Otomobil
{
// sınıfımızın parametreli yapıcı metodu...
public Otomobil(string marka, int model, string renk)
{
this.marka=marka;
this.model=model;
this.renk=renk;
}

//Property değerlerini tutacak yerel değişkenler
protected int model;
protected string marka;
protected string renk;

//Sınıfımızın property leri
public int Model
// Model property
{
get{return model;}
set{model=value;}
}

public string Marka
//Marka property
{
get{return marka;}
set{marka=value;}
}

public string Renk
// Renk property
{
get{return renk;}
set{renk=value;}
}

public override string ToString()
{
return marka + "(" + model.ToString() + "-" + renk + ")";
}

public int CompareTo(object obj)
{
if(obj==null)// null durumunda diğer sıralamalardan önce gelir.
return 1;

// Gelen nesnenin tipi otomobil değilse hata meydana gelir.
Otomobil outer=obj as Otomobil;
if(outer==null)
throw new ArgumentException();
if(this.model>outer.model)
return 1;
else if(this.model<outer.model)
return -1;
else return 0;
}
// end of method : CompareTo()

}
// end of class: Otomobil


Şimdi bu sınıfın karşılaştırma dolayısıyla sıralama mekanizmasının çalışmasına bir göz gezdirelim. Aşağıdaki test programını çalıştıralım.


/********************************************************************
*
* OTOMOBİL KOLEKSİYONU TEST KODU
*
********************************************************************/

// Dizi yapılandırılıyor...
System.Collections.ArrayList otomobiller;
otomobiller=new System.Collections.ArrayList();

// Diziye elemanlar ekleniyor...
otomobiller.Add(new Otomobil("Mercedes",2004,"Beyaz"));
otomobiller.Add(new Otomobil("BMW",2003,"Siyah"));
otomobiller.Add(new Otomobil("Opel",2002,"Kırmızı"));
otomobiller.Add(new Otomobil("Honda",2000,"Mavi"));

// Dizi elemanları sıralanıyor
otomobiller.Sort();

//Dizi döngüye alınarak elemanları ekrana yazdırılıyor...
for(int i=0;i<otomobiller.Count;i++)
{
Console.WriteLine("{0}. otomobil : {1}",i,otomobiller[i]);
}

Console.Write("Programı sonlandırmak için [ENTER] tuşuna basın.");
Console.ReadLine();

Sonuçta ekran görüntüsünde otomobillerin Model bilgilerine göre küçükten büyüğe doğru sıralandığını görürüz. Zaten bu sonuç CompareTo() metodunun amaçladığı bir sonuçtur ve sınıfın doğal karşılaştırma/sıralama davranışı budur.




Şekil 1: Otomobil sınıfının doğal sıralama sonucu


Diyelim ki otomobil sınıfı elimizde kod olarak yok da, hazır bir dll içinde var. Doğal olarak artık koda müdahale edemediğimizden, IComparable.CompareTo() metodunda da değişiklik yapamayız. Ama uygulamamızın bir yerinde otomobilleri Marka bilgilerine göre sıralamamız gerekirse ne yapacağız?
Böyle bir durumda .Net yorumcusuna yeni bir karşılaştırma yöntemi göstermemiz gerekir. .Net çatısı buna şu şekilde izin verir.


Adım 1: Öncelikle System.Collections.IComparer arayüzünü uygulayan bir sınıf yazmamız gerekmektedir. class

OtomobilMarkaKarsilastirici:System.Collections.IComparer { ... }


Adım 2: System.Collections.IComparer arayüzünün tek üyesi olan Compare() metodunu uygularız.

public int Compare(object x, object y) { ... }


System.Collections.IComparer.Compare() metodu, System.IComparable.CompareTo() metoduna çok benzer. Dönüş değeri olara yine 0, -1 ve +1 değerlendirilir. Ancak bu sefer iki parametre alır. Sonuçta

- x nesnesi (object x), y nesnesinden (object y) büyükse +1
- x nesnesi (object x), y nesnesinden (object y) küçükse -1
- x nesnesi (object x), y nesnesine (object y) eşitse 0 (sıfır)

değeri döndürülmelidir. Bunu gerçekleştirecek kodla birlikte OtomobilMarkaKarsilastirici sınıfımızın son durumu şöyle olacaktır:


/********************************************************************
*
* OTOMOBİL KARŞILAŞTIRICI SINIF KODU
*
********************************************************************/

class OtomobilMarkaKarsilastirici:System.Collections.IComparer
{

public int Compare(object x, object y)
{
Otomobil xOto=x as Otomobil;
Otomobil yOto=y as Otomobil;
if(xOto==null || yOto==null) a
throw new InvalidCastException("Hatalı parametre");

// Marka bilgileri string sınıfıyla gelen
// CompareTo() metoduyla gerçekleştiriliyor.


return xOto.Marka.CompareTo(yOto.Marka);
}

}// end of class : OtomobilMarkaKarsilastirici


Şimdi test programında tek yapmamız gereken, otomobiller listesini ekrana yazdırmadan önce sıralamak için kullandığımız kodun üzerinde ufak bir değişiklikten ibarettir:


// Dizi elemanları sıralanıyor
otomobiller.Sort()


yerine

//Dizi elemanları markalarına göre sıralanıyor
otomobiller.Sort(new OtomobilMarkaKarsilastirici());



.Net çatısıyla gelen System.Collections.IComparer arayüzünü uygulayarak, yerleşik türler (built-in classes) de dahil olmak üzere tüm sınıflar üzerinde dilediğimiz sıralama yöntemini uygulayabiliriz.

Ne demişler: Her şeyin bir şeyi var!

Hoşçakalın.