.NET platformu inanılmaz bir hızla gelişiyor. Platforma bir yandan, yeni birçok framework, kütüphane eklenirken, diğer yandan da platform dillerine geliştiricilere çok daha temiz ve hızlı geliştirme yapmalarını sağlayan birçok özellik ekleniyor.
.NET 4.0 ile yine birçok özellik C# programlama diline kazandırıldı. Bunlardan bir taneside Extension Methodlar.
Extension Methodlar, var olan C# tiplerine yeni methodlar eklememizi sağlayan yapılardır.
Bilindiği gibi C#, nesne yönelimli bir dildir. Nesne yönelimli programlamanın en önemli özelliklerinden biri de kuşkusuz inheritance(kalıtım) yapısıdır. Bu yapı ile var olan sınıflar genişletilerek, sınıflara kullanım amacımıza hizmet eden yeni işlevsellikler kazandırılır. Object – Oriented programlamada bir tipe ( örn : sınıf) ihtiyacımız doğrultusunda yeni metodlar kazandırmanın tek yolu budur. Ancak C#, .NET 4.0 ile beraber bu yapının biraz dışına çıkıyoruz.
Konuya bir örnek üzerinden devam etmek istiyorum. Hem otomobillere özel bir ilgim olmasından hem de internet üzerinde otomobil örneklerinin bu konuyu daha iyi anlatmasından dolayı bende bu örnek üzerinden yola çıkmayı planlıyorum.
Öncellikle OtomobilAlpha adında bir sınıfımızın olduğunu ve bu sınıfın otomobil nesnemizin isim ve hizini tuttuğunu varsayalım.
Otomobilimizin hizlanmasi için gerekli olan metodu OtomobilAlpha sınıfımızı genişleterek sınıfımıza ekleyelim. Varolan OtomobilAlpha sınıfımızı genişleterek ve artık hızlanan bir otomobilimiz olduğuna göre de, Otomobil sınıfımızı oluşturalım.
Artık otomobilimiz hizlanabiliyor ve hızını gostergede okuyabiliyoruz.
Ancak burada bir sorun var. Otomobilimiz nasıl yavaşlayacak? İşte bu noktada Otomobil sınıfımıza yeni bir Frenle() methodu eklememiz gerekiyor. Bunun için object-oriented yapıda, Otomobil sınıfımız tekrar genişleterek Frenle() methodumuzu sınıfımıza kazandırmamız gerekiyor. İşte bu noktada Extension Method yapısı ile yeni bir sınıf türetme işlemi yapmadan varolan Otomobil sınıfına doğrudan Frenle() methodu ekleyebiliyoruz.
Extension Methodlar
Varolan sınıfımızı genişletmeden, yeni bir tür üretmeden sınıfımıza işlevsellik kazandırmak için extension methodları kullanabiliriz. Extension methodlar C# programlama dilinde tamamen static metodlardır. Tabi ufak bir farkla.
Extension metodlar static metodlar olmasına karşın, aslında özel bir yapıdadır. Şöyle ki, extension metodlar static metod olmasına rağmen bir sınıfın instance metodları gibi kullanılırlar.
Extension metodları oluşturmak C# dilinde oldukça basittir. Metodları oluştururken dikkat edilmesi gereken ilk nokta, extension metodların ilk parametresidir. Bu ilk parametre metod içerisinde kullanılacak argümanlardan tamamen ayrışarak, aslında hangi sınıfa bu metodun extension olarak kazandırılacağını belirtmektedir. Bu ilk parametre this anahtar sözcüğü ile başlayarak tanımlanır.
Yukarıdaki ifade ile Otomobil tipine ait bir extension method tanımlaması yapılır. Tanımlanan Frenle() metodu, sadece Otomobil tipine ait instancelar için kullanılabilir yapıdadır. İlk parametre kullanılacak sınıf tipini bildirdiğinden, bu extension metod, şu an için herhangi bir argüman almıyor. Ancak extension metodumuzu;
olarak tanımlarsak, Otomobil sınıfına ait ve 1 adet argüman alan extension metod tanımlamış oluyoruz. Bu şekilde ilk parametreden sonra vereceğimiz her tanım, extension metodumuz için bir argüman listesi oluşturur.
Burda dikkat edilmesi gereken noktalardan bir tanesi de extension method yapısı C# için bir syntatic sugar değildir. Bu yüzden bir inheritance yapısı kurmuyoruz. Oluşturulan extension metod, derleme zamanında, (compile-time) deklare edilen static metod çağrısından başka bir şey değildir. Bu yüzden object-oriented paradigmasında korunan ilkeleri (encapsulation – sarmalama) hala korumuş oluyoruz. Örneğin sınıfınızdaki private değişkenlere extension methodlardan erişemeyiz.
Artık extension metodlarla ilgili bilgi sahibe olduğumuza göre örneğimizi tamamlayabiliriz. Otomobil sınıfımıza ekleyeceğimiz 2 extension metod ile Otomobil sınıfımıza Frenle() metodlarını ekliyoruz.
Test kodumuzda şu şekilde,
Extension Method Binding Süreci
Extension Methodlar, yukarıdada açıklamaya çalıştığım gibi object-oriented yapısına ters düşen yapılar değildir. Yapılan işlem compile timeda uyguladığınız extension method çağrılarının, extension methodun deklare edildiği static method çağrılarına dönüştürülmesinden başka bir şey değildir.
Bu sebeple, extension metodların kullanımı konusunda özellikle binding sürecinde bir takım kısıtlamalar vardır. Extension metodlar ile varolan sınıflarınızın metodlarını OVERRIDE edemezsiniz. Extension metod oluşturuken, var olan tiplerinize (sınıf, interface..) ait metod imzaları ile metodlar oluşturursanız, bu metodları kullanamazsınız. C# derleyicisi, asıl sınıf veya interface içinde bulunan metodları, extension metodlara göre önceliklendirir.
Eğer bir sınıf için hazırlanan extension metod, uygulanan sınıf içerisindeki bir metod ile aynı imzaya sahip ise (metod ismi ve parametre listesi aynı ise) C# derleyicisi, çağrılan metodu, sınıf veya interface içerisinde deklare edilen metoda bağlar. Extension metod bu noktada pas geçilir.
Peki Ama Neden Extension Metodları Kullanmalıyım?
Extension metodlar .NET 4.0 ile gelen ve .NET platformunda bulunan diller ile çok daha kolay bir şekilde geliştirilme yapılması için platforma kazandırılmıştır. Aslında bir object-oriented dil için olmazsa olmaz bir yapı değildir. Extension metodlar ile yapılan herşey tamamen static helper metodlar ile de yapılabiliyor.
Ancak .NET platformu, geliştirme yaparken, çok daha temiz ve okunabilirliği yüksek kodlar yazılmasını sağlamak için extension metod gibi pekçok yapıyı dile kazandırıyor. Örneğin;
gibi bir yapı oluşturulacaksa, extension metod ile yapılan tanım çok daha okunabilir ve temiz görünüyor. Aynı şekilde bir grup içerisinde kullanılacak framework yapısı oluşturulurken de, developerların hızlı ve temiz kod geliştirmesi açısından extension metodlar kullanılabilir.
Burda önemli olan nokta aslında, .NET platformunun en büyük silahı olan Visual Studio’nun intellisense özelliğinden herhangi bir helper sınıf olmadan yararlanabilmek. Yine string örneğinden yola çıkarsak, bir stringe eklediğimiz extension method ile, herhangi bir yardımcı class yapısı kullanmadan istediğimiz metoda, string üzerinden Visual Studio’nun intellisense özelliğinden ulaşabiliyoruz. Bu oldukça büyük bir kolaylık sağlıyor.
Bunun dışında bilindiği gibi object-oriented dillerde bir sınıf, final(Java) ya da sealed(C#) olarak tanımlandı ise, bu sınıfı genişletemezsiniz. Bu gibi durumlarda, sınıfı genişletmek için yapılabilecek tek şey extension metodlardır. Örneğin C# da string sınıfı sealed olarak tanımlanmıştır ve siz string sınıfını hiçbir şekilde genişletemezsiniz. Ancak string için bir extension metod yazarak, bu sınıfa yeni metodlar kazandırabilirsiniz.
Artık WordCount metodunu, extension metodun tanımlandığı NAMESPACE i ekleyerek, yazılımınızda her string için kullanabilirsiniz
.NET 4.0 ile yine birçok özellik C# programlama diline kazandırıldı. Bunlardan bir taneside Extension Methodlar.
Extension Methodlar, var olan C# tiplerine yeni methodlar eklememizi sağlayan yapılardır.
Bilindiği gibi C#, nesne yönelimli bir dildir. Nesne yönelimli programlamanın en önemli özelliklerinden biri de kuşkusuz inheritance(kalıtım) yapısıdır. Bu yapı ile var olan sınıflar genişletilerek, sınıflara kullanım amacımıza hizmet eden yeni işlevsellikler kazandırılır. Object – Oriented programlamada bir tipe ( örn : sınıf) ihtiyacımız doğrultusunda yeni metodlar kazandırmanın tek yolu budur. Ancak C#, .NET 4.0 ile beraber bu yapının biraz dışına çıkıyoruz.
Konuya bir örnek üzerinden devam etmek istiyorum. Hem otomobillere özel bir ilgim olmasından hem de internet üzerinde otomobil örneklerinin bu konuyu daha iyi anlatmasından dolayı bende bu örnek üzerinden yola çıkmayı planlıyorum.
Öncellikle OtomobilAlpha adında bir sınıfımızın olduğunu ve bu sınıfın otomobil nesnemizin isim ve hizini tuttuğunu varsayalım.
Kod:
public class OtomobilAlpha
{
public int hiz {get; set;}
public string isim { get; set; }
public OtomobilAlpha(string isim)
{
this.isim = isim;
}
public void Gosterge()
{
Console.WriteLine("{0} adındaki otomobilimiz {1} hızında", isim, hiz);
Kod:
public class Otomobil : OtomobilAlpha
{
public Otomobil(string isim)
: base(isim)
{ }
public void Gazla()
{
hiz = hiz + 10;
Kod:
static void Main(string[] args)
{
Otomobil o = new Otomobil("Mercedes");
o.Gosterge();
o.Gazla();
o.Gosterge();
Ancak burada bir sorun var. Otomobilimiz nasıl yavaşlayacak? İşte bu noktada Otomobil sınıfımıza yeni bir Frenle() methodu eklememiz gerekiyor. Bunun için object-oriented yapıda, Otomobil sınıfımız tekrar genişleterek Frenle() methodumuzu sınıfımıza kazandırmamız gerekiyor. İşte bu noktada Extension Method yapısı ile yeni bir sınıf türetme işlemi yapmadan varolan Otomobil sınıfına doğrudan Frenle() methodu ekleyebiliyoruz.
Extension Methodlar
Varolan sınıfımızı genişletmeden, yeni bir tür üretmeden sınıfımıza işlevsellik kazandırmak için extension methodları kullanabiliriz. Extension methodlar C# programlama dilinde tamamen static metodlardır. Tabi ufak bir farkla.
Extension metodlar static metodlar olmasına karşın, aslında özel bir yapıdadır. Şöyle ki, extension metodlar static metod olmasına rağmen bir sınıfın instance metodları gibi kullanılırlar.
Extension metodları oluşturmak C# dilinde oldukça basittir. Metodları oluştururken dikkat edilmesi gereken ilk nokta, extension metodların ilk parametresidir. Bu ilk parametre metod içerisinde kullanılacak argümanlardan tamamen ayrışarak, aslında hangi sınıfa bu metodun extension olarak kazandırılacağını belirtmektedir. Bu ilk parametre this anahtar sözcüğü ile başlayarak tanımlanır.
Kod:
public static void Frenle(this Otomobil otomobil)
Kod:
public static void Frenle(this Otomobil otomobil, string yeniIsim)
olarak tanımlarsak, Otomobil sınıfına ait ve 1 adet argüman alan extension metod tanımlamış oluyoruz. Bu şekilde ilk parametreden sonra vereceğimiz her tanım, extension metodumuz için bir argüman listesi oluşturur.
Burda dikkat edilmesi gereken noktalardan bir tanesi de extension method yapısı C# için bir syntatic sugar değildir. Bu yüzden bir inheritance yapısı kurmuyoruz. Oluşturulan extension metod, derleme zamanında, (compile-time) deklare edilen static metod çağrısından başka bir şey değildir. Bu yüzden object-oriented paradigmasında korunan ilkeleri (encapsulation – sarmalama) hala korumuş oluyoruz. Örneğin sınıfınızdaki private değişkenlere extension methodlardan erişemeyiz.
Artık extension metodlarla ilgili bilgi sahibe olduğumuza göre örneğimizi tamamlayabiliriz. Otomobil sınıfımıza ekleyeceğimiz 2 extension metod ile Otomobil sınıfımıza Frenle() metodlarını ekliyoruz.
Kod:
public static void Frenle(this Otomobil otomobil)
{
if (otomobil.hiz > 0)
{
if ((otomobil.hiz -= 5) <= 0)
{
otomobil.hiz = default(int);
}
else
{
otomobil.hiz -= 5;
}
}
}
public static void AniFren(this Otomobil otomobil, int yeniHiz)
{
if (otomobil.hiz > 0)
{
if ((otomobil.hiz -= yeniHiz) <= default(int))
{
otomobil.hiz = default(int);
}
else
{
otomobil.hiz -= yeniHiz;
}
}
}
Test kodumuzda şu şekilde,
Kod:
class Program
{
static void Main(string[] args)
{
Otomobil o = new Otomobil("Mercedes");
o.Gosterge();
o.Gazla();
o.Gazla();
o.Gosterge();
o.Frenle(); //extension method
o.Gosterge();
o.AniFren(15); //extension method
o.Gosterge();
o.Frenle();
o.Gosterge();
}
}
Extension Method Binding Süreci
Extension Methodlar, yukarıdada açıklamaya çalıştığım gibi object-oriented yapısına ters düşen yapılar değildir. Yapılan işlem compile timeda uyguladığınız extension method çağrılarının, extension methodun deklare edildiği static method çağrılarına dönüştürülmesinden başka bir şey değildir.
Bu sebeple, extension metodların kullanımı konusunda özellikle binding sürecinde bir takım kısıtlamalar vardır. Extension metodlar ile varolan sınıflarınızın metodlarını OVERRIDE edemezsiniz. Extension metod oluşturuken, var olan tiplerinize (sınıf, interface..) ait metod imzaları ile metodlar oluşturursanız, bu metodları kullanamazsınız. C# derleyicisi, asıl sınıf veya interface içinde bulunan metodları, extension metodlara göre önceliklendirir.
Eğer bir sınıf için hazırlanan extension metod, uygulanan sınıf içerisindeki bir metod ile aynı imzaya sahip ise (metod ismi ve parametre listesi aynı ise) C# derleyicisi, çağrılan metodu, sınıf veya interface içerisinde deklare edilen metoda bağlar. Extension metod bu noktada pas geçilir.
Peki Ama Neden Extension Metodları Kullanmalıyım?
Extension metodlar .NET 4.0 ile gelen ve .NET platformunda bulunan diller ile çok daha kolay bir şekilde geliştirilme yapılması için platforma kazandırılmıştır. Aslında bir object-oriented dil için olmazsa olmaz bir yapı değildir. Extension metodlar ile yapılan herşey tamamen static helper metodlar ile de yapılabiliyor.
Ancak .NET platformu, geliştirme yaparken, çok daha temiz ve okunabilirliği yüksek kodlar yazılmasını sağlamak için extension metod gibi pekçok yapıyı dile kazandırıyor. Örneğin;
Kod:
string str = "Türkiye Cumhuriyeti";
int i = str.WordCount();
int j = StringUtil.WordCount(str);
gibi bir yapı oluşturulacaksa, extension metod ile yapılan tanım çok daha okunabilir ve temiz görünüyor. Aynı şekilde bir grup içerisinde kullanılacak framework yapısı oluşturulurken de, developerların hızlı ve temiz kod geliştirmesi açısından extension metodlar kullanılabilir.
Burda önemli olan nokta aslında, .NET platformunun en büyük silahı olan Visual Studio’nun intellisense özelliğinden herhangi bir helper sınıf olmadan yararlanabilmek. Yine string örneğinden yola çıkarsak, bir stringe eklediğimiz extension method ile, herhangi bir yardımcı class yapısı kullanmadan istediğimiz metoda, string üzerinden Visual Studio’nun intellisense özelliğinden ulaşabiliyoruz. Bu oldukça büyük bir kolaylık sağlıyor.
Bunun dışında bilindiği gibi object-oriented dillerde bir sınıf, final(Java) ya da sealed(C#) olarak tanımlandı ise, bu sınıfı genişletemezsiniz. Bu gibi durumlarda, sınıfı genişletmek için yapılabilecek tek şey extension metodlardır. Örneğin C# da string sınıfı sealed olarak tanımlanmıştır ve siz string sınıfını hiçbir şekilde genişletemezsiniz. Ancak string için bir extension metod yazarak, bu sınıfa yeni metodlar kazandırabilirsiniz.
Kod:
public static int WordCount(this string str)
{
return 0;
}
Artık WordCount metodunu, extension metodun tanımlandığı NAMESPACE i ekleyerek, yazılımınızda her string için kullanabilirsiniz
Kod:
"fatih".WordCount();
str s = "Java Blog";
s.WordCount();