Makale Özeti

C# 3.0 ile birlikte gelen pek çok yenilik arasında beni gerçekten sevindiren bir özellik var. 2.0 ve öncesinde gerçekten uğraştırıcı bir işi son derece kolaylaştıran extension methods. Bu makalede extension methods'In ne olduğunu, nerelerde kullanabileceğimizi ve neden beni bu kadar sevindirdiğini anlatıyor olacağım.

Makale

Kısaca basit bir tanımını yapmak gerekirse extension methods sadece static classlar içinde tanımlanabilen, parametre tanımlamalarında türden önce this ifadesini kullandığımız ve standart CLR türlerine yeni metodlar eklemek amacıyla kullandığımız static metodlardır. Hemen basit bir örnek ile extension metodların uygulamasını görelim;

İlk olarak aşağıdaki static class'ı hazırlıyoruz*:

public static class extensionMethods
{
         
public static int ToInt32Ext(this string s)
          {
                   
return Int32
.Parse(s);
          }

          public static int ToInt32Static(string s)
          {
                   
return Int32
.Parse(s);
          }
}

Hemen sonrasında bu classta tanımladığımız metodları kullanıyoruz;

private void button1_Click(object sender, EventArgs e)
{
         
string s = "9";

         
int i = s.ToInt32Ext(); // extension method kullan�m�
          label1.Text = i.ToString();

         
int j = EMClass.ToInt32Static(s); // standart kullan�m metodu
          label2.Text = j.ToString();
}

Örneğimizi inceleyecek olursak;
1. ToInt32Ext metodunda parametrelerimizi tanımlarken tür ifadesinden önce this keywordunu kullanıyoruz.
2. Extension Methodları kullanırken this ile tanımladığımız parametreyi göndermiyoruz. Yukarıdaki örnekte görebileceğiniz gibi Extension Methodu kullanırken herhangi bir parametre göndermedim, ancak static metodu kullanırken gerekli parametreyi gönderdim.
3. Extension methodlar sadece static classların içinde tanımlanabilirken static metodlar için böyle bir zorunluluk bulunmamaktadır.
4. Extension methodlar sadece instance değerler üzerinden çağrılabilir. Bir class içinden çağırmaya çalışmamız halinde compile time hatası alırız.

Email Adresi Denetimi
string türünün metodları arasında bildiğimiz gibi objenin kaç karakterden oluştuğunu veren Length, karakterleri büyük harfe çeviren ToUpper, ya da tam tersini yapan ToLower metodları gibi metodlar bulunmaktadır. Doğal olarak tasarım aşamasında string türü için IsValidEmailAddress şeklinde değişkene atanan değerin geçerli bir email adresi olup olmadığını denetleyecek, belirli bir gereksinime yönelik bir fonksiyon oluşturulamazdı ve bu işlemi yapmak için değişkenimizi yazdığımız denetim fonksiyonuna gönderirdik. Extension Methods sayesinde string türüne email adresi denetimini yapacak bir fonksiyon hazırlayarak bunu instance'ın kendisinden çağırabiliyoruz. Hemen örnekliyoruz;

İlk olarak extensionMethods classımıza aşağıdaki denetim fonksiyonunu ekliyoruz;

public static bool IsValidEmailAddress(this string s)
{
          Regex regex =
new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
         
return regex.IsMatch(s);
}

Hemen ardından test formumuzun içinden bu fonksiyonu kullanıyoruz;

private void button1_Click(object sender, EventArgs e)
{
          string email = "kadir@sumerkent.com";
          bool result = email.IsValidEmailAddress();
}


Şekil 1: IntelliSense içinden extension methoda erişim

Bu kullanımın sonucunda result değişkeni true değerini alacaktır, ancak email değişkeninde geçersiz bir email adresi yazmış olsaydım false değerini alacaktı.

Kullanımımızı aşağıdaki gibi değiştirerek email değişkenine geçersiz bir email adresi belirtirsek, çalışma zamanında button tıklandığında bir hata mesajı alırız.

private void button1_Click(object sender, EventArgs e)
{
         
string email = "kadir@sumerkent.com";
          if(!email.IsValidEmailAddress())
          {
                    MessageBox.Show("Invalid email address specified.");
          }
}

LINQ
Elbette extension methodlar bu kadarla sınırlı değil. Bu fonksiyonun asıl önemi, LINQ devreye girdiği zaman ortaya çıkıyor.

Şirketimizdeki çalışanların listesini tutarken kullanmak için basit bir employee classı oluşturalım;

    public class Employee
    {
        public string Name
        {
            get; set;
        }
        public string LastName
        {
            get; set;
        }
        public int Age
        {
            get; set;
        }
        public decimal Salary
        {
            get; set;
        }
 
        public string Email
        {
            get; set;
        }
    }

Şimdi employee instanceları içeren bir generic list oluşturalım ve bir kaç sorgu çalıştıralım;

       List<Employee> employees = new List<Employee>();
       employees.Add(new Employee { Name = "Kadir", LastName = "Sümerkent", Age = 26, Salary = 100, Email = "kadir@sumerkent.com" });
       employees.Add(new Employee { Name = "Bill", LastName = "Gates", Age = 50, Salary = 1000, Email = "bill@gates.com" });
       employees.Add(new Employee { Name = "Steve", LastName = "Ballmer", Age = 30, Salary = 800, Email = "steve@ballmer.com"});
       employees.Add(new Employee { Name = "Bakkal Orkun", LastName = "Balkancı", Age = 29, Salary = 50, Email = "bakkal@" });
       employees.Add(new Employee { Name = "Seda", LastName = "Sayan", Age = 18, Salary = 5000, Email="seda" });

Şimdi bu liste üzerinde LINQ ile bir kaç sorgu çalıştıralım;

    IEnumerable<Employee> result;
 
    //Maaşı 500'den büyük olan personelin listesi
    result = employees.Where(emp => emp.Salary > 500);
 
    //Yaşı 30'dan yüksek olan personelin listesi
    result = employees.Where(emp => emp.Age > 30);
 
    //İsmi B ile başlayan personelin listesi
    result = employees.Where(emp => emp.Name.StartsWith("B"));
 
    //email adresi geçersiz olan personelin listesi
    result = employees.Where(emp => !emp.Email.IsValidEmailAddress());

Buraya kadar Extension Methodların ne olduğunu ve nasıl kullanılabileceğini ele aldık, bir sonraki makalede Framework 3.0 ve 3.5 ile gelen diğre yenilikleri ele alıyor olacağız.

Kadir Sümerkent
kadir@sumerkent.com

 

 

 

 

 

 

 

Kaynaklar;
* Vipul Patel: Using the New Extension Methods Feature in C# 3.0
* MSDN