-- C#

İleri C# : Jenerik Sınıflar ve İleri Seviye Jenerik İşlemleri – 1

Merhabalar,

.NET Framework mimarisi destekli bir programlama dilleriyle ilgilenen dostların yakinen bildiği terimlerden ikisi aşağıdaki gibidir;

  • Koleksiyonlar (Şuan okuduğunuz makale)
  • Jenerikler

Bu iki terimden koleksiyonları detaylı incelemeyeceğiz, sadece temel bir bakış ve jeneriklerle olan bağlantısına odaklanıp doğru jeneriklere geçeceğiz.

Bu makalede asıl amacımız kendi gelişmiş jenerik sınıflarımızı, metot ve interface’lerimizi geliştirmek olacaktır.

Koleksiyonlar

Bildiğim tüm programlama dillerinde programcıların liste nesnelerine ihtiyacı vardır. Bu liste nesnelerini bir sepet ya da yumurta küfesi olarak düşünebilirsiniz. Bir alışveriş sepetine birden fazla tipte ürün yerleştirebilirsiniz değil mi? Aynı şekilde sadece yumurta yerleştirmek istediğiniz bir yumurta küfesi de ihtiyaç dahilinde bir tercih olabilir.

Geliştirdiğimiz yazılımlarda alışveriş sepeti olarak değerlendirebileceğimiz liste türüne “obje tipi alan koleksiyonlar” diyoruz. İçerisine elma, armut, yumurta, patates vb. her şey yerleştirebilirsiniz. Çünkü içerisine object(obje) nesnesi alıyordur. OOP mimarilerinde object nesnesi tüm Framework’ün temelini oluşturan nesnelerden biridir. Yani her şey teknik olarak bir obje’den türediği için aslında her şey bir objedir!

.NET Framework’de object  alan koleksiyonlarımızın en bilindiği ArrayList nesnesidir. Şimdi bu nesne ile ilgili bir örnek yapalım.

Öncelikle, ArrayList nesnesini kullanabilmemiz için using alanında aşağıdaki namespace’i tanımlamamız gerekir.

using System.Collections;

Bu tanımlamadan sonra ArrayList’i kullanabilir olacağız.

ArrayList pLanguages = new ArrayList();
pLanguages.Add("C#");
pLanguages.Add("Java");

Yukarıdaki pLanguages adındaki ArrayList koleksiyonumuz programlama dillerinin bir listesi olarak oluşturulmuştur. Herhangi bir sorun yok, işimizi görüyor… Yalnız programlama dilleri string tipine sahiptir. Peki farklı tipleri alabilir mi? Evet, alabilir… Örneğin;

ArrayList pLanguages = new ArrayList();
pLanguages.Add("C#");
pLanguages.Add("Java");
pLanguages.Add(true); // boolean
pLanguages.Add(4.3M); // decimal
pLanguages.Add(new object());

Yukarıdaki örneğimizde pLanguages koleksiyonumuz boolean, decimal ve object tipinde farklı veri tiplerini de sorunsuz bir şekilde koleksiyona atayabilmektedir. Eğer kullanmak isterseniz pLanguages listesinin indekslerini gezerek tüm veriyi elde edebilirsiniz. Tabi ki farklı tipleri kendi doğal tipleri şeklinde almak isterseniz her indeks deki veriyi GetType() ya da farklı tip öğrenme yöntemiyle tipini öğrenip o şekilde kendi tipinde bir nesneye atamalısınız.

ArrayList yalnız değildir, farklı bir çok object alan koleksiyon tipi mevcuttur. Bu koleksiyon tipleri gereksiz değildir ve bazı durumlarda ciddi işleri kolaylaştırabiliyor. Ancak beraberinde performans ve tip güvenliği gibi iki önemli kavramı beraberinde getirdiği durumlar da söz konusu olmaktadır. Peki nasıl?

Tip güvenliği konusunda basit bir object işlemi gerçekleştirelim;

object objX = 3;
Console.WriteLine("Data : " + objX);
Console.WriteLine("Type : " + objX.GetType());

objX = "Cihan Özhan";
// ya da
objX = 4.3M; // decimal

Console.WriteLine("Data : " + objX);
Console.WriteLine("Type : " + objX.GetType());

Bu uygulamayı konsol üzerinden çalıştırdığımızda aşağıdaki gibi bir çıktı alırız.

1

 

 

 

Buraya kadar gayet normal. Ancak dikkat ederseniz normalde bir değişkenin veri tipinin değiştirilmesi istenen bir durum değildir. Bir değişken int ise int, string ise string olarak kalmalıdır(istisnalar hariç…). Object nesnesi tip güvenliği sağlamaz, string tipinde atadığınız değişkenin değerini de tipini de değiştirebilirsiniz.

Olması istenen ise başlangıçta bir değişken tanımlayayım, ona gelen değer ne ise onun tipini de değerini de alsın ve sonrasında değeri değiştirilebilsin ancak tipi değiştirilemesin durumudur.

Bu isteği object değil, var tipi sağlar.

var objX = 3;
Console.WriteLine("Data : " + objX);
Console.WriteLine("Type : " + objX.GetType());

Yukarıdaki örnek başarıyla çalışır ve aşağıdaki çıktıyı üretir.

2

 

 

Ancak aşağıdaki örnek derlenmeyecektir.

var objX = 3;
Console.WriteLine("Data : " + objX);
Console.WriteLine("Type : " + objX.GetType());

objX = "Cihan Özhan";
// ya da
objX = 4.3M; // decimal

Console.WriteLine("Data : " + objX);
Console.WriteLine("Type : " + objX.GetType());

Bunun nedeni objX değişkeninin başlangıçta var sayesinde int tipini alması ve sonrasında string ve decimal ile değiştirilmek istenmesidir. Zaten daha derlemeden editör size kodun altını kırmızı ile işaretleyerek hatayı gösterecektir.

Şu ana kadar object ve var anlatımım ile object nesnesi alan koleksiyonlardaki tip güvenliği konusuna değindim. Bunun bir diğer bacağı ise daha önce belirttiğim gibi performans idi. Object tipi her tipi kendine dahil edebiliyor. Ancak object’e atadığınız değeri(tipiyle birlikte) geri elde etmek istediğinizde bir tür dönüşümü yapmanız gerekmektedir. Yani int’den int’e atama yapar gibi yapamayız. “Object to X” tip dönüşümü yapılırken ise doğal olarak bir zaman ve kaynak tüketimi meydana gelmektedir. Bu da performans kaybına yol açar.

Şu ana kadar object tipi alan koleksiyonları anlatmaya çalıştım. Peki bu sorunların çözümü nedir diye sorabilirsiniz. Cevabımız Jenerik’ler… Ohh be! Buraya hiç gelemeyeceğim sandım bir an!

Ancak makale çok uzadı. Bundan sonraki konular şu ana kadar olanlardan daha uzun olacak. Bu nedenle ilgili konuları bu makalenin devamında anlatacağım.

İyi çalışmalar.
Cihan Özhan

Yorumla

Yorum