C#'ta Çevrim Operatörü (Convertion Operator)

Eyl 06, 2013

Bir veri tipi  oluşturulup daha sonra kullanılacağı zaman, o veri tipini başka veri tiplerine çevirmek gerekebilir. Bir alt sınıftan türeyen tiplerin başka bir alt sınıfa çevrilmesi mümkündür. Örnek vermek gerekirse Control sınıfının bir örneğine bir Textbox sınıfı atanabilir. Çünkü Textbox Control'den türemiştir. Her ikisi de aynı sınıftan türemiş olsa bile bir sınıftan başka bir sınıfa atama yapılamayabilir veya dönüştürülemeyebilir. Bu çevirme işlemleri Framework1.1'de gerçekleştirilirken,"object" veri tipine çevrilmekteydi fakat bu yöntem fazla işlem zamanına sebep olmakta veya hiç gerçekleşmemekteydi. Bu tip bir durumdan kurtulmak için kullanılan yöntem ise bir fonksiyon yardımıyla bu işi çözmekti. Framework2.0 ile birlikte gelen çevrim operatörü bu soruna daha güzel bir çözüm getirerek çevrim işlemlerinin tanımlı veri tiplerindeki gibi zahmetsiz gerçekleştirilmesini sağlamıştır.
Çevrim işlemi, implicit (dolaylı) ve explicit (doğrudan) olmak üzere 2 ayrı operatörle yapılabilir.

implicit: implicit operator ile sınıflar birbirine hiçbir casting (çevirme) veya convert (dönüştürme) işlemi yapmadan atanabilir hale getirilebilir. Bunun için sınıfların aynı sınıftan türemiş olmalarına gerek yoktur.Implicit operator ile ilgili aşağıdaki gibi bir örnek verilebilir.
Aşağıdaki gibi bir sınıf olduğu varsayılsın.

    public class Currency
    {
        public decimal Value { get; set; }
        public string Sign { get; set; }
    }

 Bu sınıf şu şekilde kullanılabilir.

            //sınıfin bir örneği alinir.
            Currency c = new Currency();
            c.Value = 12;
            c.Sign = "$";
            //simdi bu sinifa bir decimal deger atanabilir.
            decimal d = c; //<-- Bu satirda Connot implicitly convert type Currency to decimal hatasi verecektir.

Bu hatayı almamak için bu sınıfa bir implicit operator yazılır.

    public class Currency
    {
        public decimal Value { get; set; }
        public string Sign { get; set; }
        public static implicit operator decimal(Currency c)
        {
            return c.Value;
        }
     }

Bu operatörü yazdıktan sonra kod hata vermeyecektir ve yukarıdaki dönüştürme işlemi otomatik olarak implicit şekilde yapılacaktır.

explicit: explicit operator tanımlanarak sınıflar birbirine dolaylı olarak dönüştürülebilir hale getirilebilir. Bunun için aynı sınıftan türemiş olmalarına da gerek yoktur. Implicit operator tanımlanmış bir sınıfı diğerine çevirirken derleyici hiçbir hata vermez dolayısıyla bu iki sınıfı birbirine çevirirken bir veri kaybı veya sınıf şemalarında bir olumsuzluk oluyorsa bile farkedilemez. Böyle durumlarda explicit operator kullanılması tercih edilmelidir. Explicit operator tanımlanmış bir sınıf, diğerine  doğrudan atanamadığından ve derleyici her durumda dönüştürülmesini istemediğinden geliştirici bu işlemde bazı olumsuzluklar olabileceğini düşünür ve her iki sınıfın yapılarını karşılaştırır. Explicit operator ile ilgili aşağıdaki gibi bir örnek verilebilir.
Yine aynı sınıfları kullanılır. Sadece karışmaması için isimler değiştirilebilir.

    public class CurrencyExplicit
    {
        public decimal Value { get; set; }
        public string Sign { get; set; } 
    }

Yine aynı atama örneği denenir.

            CurrencyExplicit insCurrencyExplicit = new CurrencyExplicit();
            insCurrencyExplicit.Value = 12;
            insCurrencyExplicit.Sign = "$";
            decimal d  =  insCurrencyExplicit; //bu atama islemi yapilamiyor.

Hata verdiği için sınıfa explicit bir operator eklenir.

    public class CurrencyExplicit
    {
        public decimal Value { get; set; }
        public string Sign { get; set; }
        public static explicit operator decimal(CurrencyExplicit c)
        {
            return c.Value;
        }
    }

Atama işlemi tekrar yapılmak istendiğinde bu satırda derleyicinin hala hata verdiği görülebilir. Verdiği hata "Cannot implicitly convert type 'CurrencyExplicit' to 'decimal'. An explicit conversion exists are you missing a cast?(Tipler birbirine çevrilemiyor ama explicit bir çevrim içeriyor. Dönüştürmeyi atlıyor olabilir misiniz?)" hatasıdır.

            CurrencyExplicit insCurrencyExplicit = new CurrencyExplicit();
            insCurrencyExplicit.Value = 12;
            insCurrencyExplicit.Sign = "$";
            //decimal d1 = insCurrencyExplicit; //bu atama islemi yapilamiyor.
            decimal d1 = (decimal)insCurrencyExplicit;

Bu durumda çevrim işlemi tanımlandı ancak doğrudan çevirmeye derleyici izin vermedi ve elle dönüştürmemizi istedi. Değiştirilecek tip parantez içinde nesnenin önüne eklenir. Bu durumda veri kayıpları olacak ise, örneğin sign değeri kaybolacak ise geliştirici bunun farkına varabilir.