C# Extension Methods

Genişletme metodları bir tip (integer veya string vb.) üzerinde herhangi bir değişiklik yapmadan o tipi kolayca genişletmemize olanak sağlayan bir yapıdır. Daha basit olarak anlatacak olursak tanımladığımız bu Genişletme Metodları özünde bildiğimiz static metodlardır. .Net Framework 3.5 ile kullanıma gelmişlerdir, .Net Frameworkte içerisinde bulunan ve tanımlamış olduğumuz her tip için uygulanabilmektedir.

Eğer bir tip için var olan öz metodlar ile aynı isimde extension metod oluşturursanız, derleyici (compiler) metod çağırımında yazmış olduğunuz extension metodu değil öz metodu çalıştıracaktır. Extension metodlar sadece aynı isimde öz metod olmadığı zaman çalışırlar.

Unutmamak gerekir ki Object tipine tanımladığınız bir extension metod, sadece String, Integer ve List’ler için kısıtlı kalmayıp .Net Framework içerisindeki her tip için geçerli olacaktır.

Nasıl Genişleme metodu oluşturulur?

Genişletme metodlarını basit bir şekilde tanımlayacak olursak yapmamız gereken adımlar aşağıdaki gibi olacaktır.

1. Public static bir sınıf oluşturulur.
2. Yapmak istediğiniz işlemleri gerçekleştirecek metod yazılır.
3. Fonksiyon genişleme metoduna dönüştürülür.

Yazının devamında yapacağım ilk örnekte bir extension metodu nasıl tanımlayacağımızı ve bu metod ile string bir tipin ilk 3 karekterini geri dönüş değeri olarak döndüreceğiz. İlk önce static sınıf tanımlıyoruz.

// C#
public static class Extensions
{

}

Sonrasında ihtiyacımız olan metodu sınıf içerisine aşağıdaki şekilde tanımlıyoruz :

// C#
public static class Extensions
{
    public string GetFirstThreeCharacters(String str)
    {
        if(str.Length < 3)
        {
            return str;
        }
        else
        {
            return str.Substring(0,3);
        }
    }
}

Şimdiye kadar özel bir işlem yapmadık. Son aşama olarak oluşturduğumuz metodları extension metod’a dönüştürmek kaldı.

İlk olarak metoduda static yapmamız gerek (böylece herhangi bir tanımlama yapmadan istediğimiz zaman erişebilelim) ikinci olarak ilk parametrenin başına this kelimesini koyuyoruz. Parametremizin başına this kelimesini koymakla CLR’a metodumuzun extension metod olduğunu bildirmiş oluyoruz. Kodumuz sonrasında aşağıdaki gibi olacaktır :

public static class Extensions
{
    public static string GetFirstThreeCharacters(this String str)
    {
        if(str.Length < 3)
        {
            return str;
        }
        else
        {
            return str.Substring(0,3);
        }
    }
}

Bu kodları herhangi bir projeye kopyaladığımızda, aşağıdaki gibi bir ifade ile oluşturduğumuz extension metodları kullanabilmekteyiz :

// C#
String str = "Genişletme metodları";
str = str.GetFirstThreeCharacters();

Extension method kulllanımına ilişkin örnekler

HasElements

Bazı durumlarda koleksiyonlarda bir değer olup olmadığını kontrol ederiz. Aşağıdaki metod sayesinde her defasında çalışılan koleksiyonun null yada içerisinde bir öğe (item) olup olmadığını anlamak için tek tek kontrol etmemi engellemektedir. Bu metod ICollection interface’i ile genişletilmiş tüm tiplerde kullanılabilir.

public static bool HasElements(this ICollection items)
{
    return items != null && items.Count > 0;
}

Örnek kullanımı :

List myList = new List();
if (myList.HasElements())
{
   // işlemler
}

IsBetween

Çalıştığımız tip üzerinde IsBetween metodu ile belirttiğininiz değerin verdiğimiz alt ve üst limitler arasında olup olmadığını kontrol edebiliriz. Bu metod IComparable interface’i ile genişletilmiş tüm tiplerde kullanılabilir.

Definition:

public static bool IsBetween<T>(this T value, T low, T high) where T : IComparable<T>
{
    return value.CompareTo(low) >= 0 && value.CompareTo(high) <= 0;
}

Örnek kullanımı :

Int32 myInt = 0;
myInt.IsBetween(0, 5); // true döner
myInt.IsBetween(1, 5); // false döner

Each

Sıklıkla koleksiyonlar üzerinde belirli işlemler gerçekleştirmekteyiz. Bu extension metod ile koleksiyondaki her öğe (item) için belirli bir Action<> gerçekleştirebilirsiniz. Bu metod ICollection interface’i ile genişletilmiş tüm tiplerde kullanılabilir. Ayrıca Action<> delegesini lambda ifadeleri ile düzenleyip kulllanabilirsiniz.

public static void Each<T>(this ICollection<T> items, Action<T> action)
{
    foreach (T item in items)
    {
        action(item);
    }
}

Örnek kullanım :

List myList = new List();
myList.Each(el =>
{
    // Her öğe (item) için bir Action gerçekleştiriliyor.
    el.Substring(0,1);
    el = el;
});

In

Bu metod ile bir öğe (item)’in koleksiyon içerisinde olup olmadığını kontrol etmek için kullanılabilir. Örneğin string bir ifadenin string bir koleksiyonda olup olmadığını kontrol edebilirsiniz. Bu metod aynı tipi barındıran tüm dizilerde kullanılabilir.

public static bool In<T>(this T source, params T[] list)
{
    if (null == source) throw new ArgumentNullException("source");
    return list.Contains(source);
}

Örnek kullanım :

Int32 myInt = 0;
myInt.In(0, 0, 1, 2, 3); // true döner
myInt.In(1, 5, 6, 7, 8); // false döner

Son olarak koleksiyon içerisinde tekrar eden kayıtları silmenize yarayacak bir örnek extension metod :

public static List<T> RemoveDuplicates<T>(this List<T> input)
{
    Dictionary<T, int> uniqueStore = new Dictionary<T, int>();
    List<T> finalList = new List<T>();

    foreach (T currValue in input)
    {
        if (!uniqueStore.ContainsKey(currValue))
        {
            uniqueStore.Add(currValue, 0);
            finalList.Add(currValue);
        }
    }
    return finalList;
}
Daha fazla örnek bulabileceğiniz ExtensionMethod.NET sitesini ziyaret etmenizi özellikle tavsiye ederim.

Kaynak ;

MSDN: Extension Methods (C# Programming Guide)
ExtensionMethod.NET

Bir cevap yazın