Makale Özeti

Implicit ve Explicit operator ile bir tipin başka bir tipe çevrilebilirliğini tanımlıyor olacağız tabii ki bir base classdan türeyen tiplerin base class a çevrilmesi mümkündür. Örnek vermek gerekirse Control class'ının bir örneğine bir Textbox class'ını atayabiliriz. Çünkü TextBox kontrolden türemiştir. Ama bir elma class'ına bir armut class'ını her ikisi de meyve class'ından türemiş olsa bile atayamayız. Ayrıca bir birine cast edemeyiz de. Implicit operator ile bu class'ları birbirlerine hiçbir casting veya convert işlemi yapmadan atanabilir hale getirebiliriz. Bunun için bu class'ların aynı class'dan türemiş olmalarına gerek yok. İmplicit operator ile ilgili bir örneği de makalemin ilerleyen kısımlarında beraber yapacağız.

Makale

Merhabalar,

Daha önce http://www.yazgelistir.com/Makaleler/1000000514.ygpx adresinde yayınlanmış oldığum makalede operator overloading konusunu incelemiştik. Bu makalemde ise implicit ve explicit operator'ler üzerinde duracağız. Bu 3 operatör temel olarak tipler üzerinde işlem yapmamıza yaramaktadır.

Hatırlayacak olursak operator overloading ile tipler arasında bölme, çarpma, çıkarma, toplama gibi işlemleri yapmamız mümkün olmaktaydı. Tabii ki bu işlemlerin nasıl yapılacağına dair kodları kendimizin yazması gerekiyor.

Implicit ve Explicit operator ile bir tipin başka bir tipe çevrilebilirliğini tanımlıyor olacağız tabii ki bir base classdan türeyen tiplerin base class a çevrilmesi mümkündür. Örnek vermek gerekirse Control class'ının bir örneğine bir Textbox class'ını atayabiliriz. Çünkü TextBox kontrolden türemiştir. Ama bir elma class'ına bir armut class'ını her ikisi de meyve class'ından türemiş olsa bile atayamayız. Ayrıca bir birine cast edemeyiz de.

Implicit operator ile bu class'ları birbirlerine hiçbir casting veya convert işlemi yapmadan atanabilir hale getirebiliriz. Bunun için bu class'ların aynı class'dan türemiş olmalarına gerek yok. İmplicit operator ile ilgili bir örneği de makalemin ilerleyen kısımlarında beraber yapacağız.

Explicit bir operator tanımlayarak biz bu class'ları birbirine explicit olarak cast edilebilir hale getirebiliriz. Bunun için aynı class'dan türemiş olmalarına da gerek yok. Bunu makalemizin ilerleyen kısımlarında bir örnekle daha net açıklamaya çalışacağım.

İmplicit operator tanımlanmış bir class'ı diğerine çevirirken compiler hiçbir hata vermez dolayısıyla bu iki class'ı birbirine çevirirken bir veri kaybı veya bir class şemalarında bir olumsuzluk oluyorsa developer bunu hiçbir zmaan anlayamaz. Böyle durumlarda explicit operator kullanılması tercih edilmelidir. Explicit operator tanımlanmış bir class diğerine direkt atanamadığından ve compiler illa ki cast edilmesini istediğinden developer bu işlemin bazı olumsuzlukları olabileceğini düşünecek ve her iki class'ın yapılarını karşılaştıracaktır.

Şimdi isterseniz implicit operator ile ilgili örnek yapalım.

Aşağıdaki gibi bir class'ımız olduğunu düşünelim.

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

Bu class'ımızı şu şekilde kullanmaya çalışalım.

            //class imizin bir instance ini aliyoruz
            Currency c = new Currency();
            c.Value = 12;
            c.Sign = "$";
            //simdi bu class'imizi bir decimal degere atamaya calisalim.
            decimal d = c; //<-- Bu satirda Connot implicitly convert type Currency to decimal hatasi verecektir.

Şimdi bu işlemi implicit operator ile nasıl yapılabilir kılacağımızı inceleyelim. Bu işlem için class'ımıza bir implicit operator yazıyoruz.

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

Bunu operatoru yazdıktan sonra kodumuz hata vermeyecektir ve yukarıdaki cast işlemi implicit olarak yapılacaktır.

Implicit operator syntax'ına baktığınızda publIs static implicit operator CevrilecekTip(MevcutTip) olarak bir syntax görüyorsunuz. Kullanımı oldukça basit.

Ancak burada dikkat edilmesi gereken bir nokta bu işlem sorunsuz bir şekilde yapılmakta ve Currency'nin sign property'sinde ki değer bu adımdan sonra kullanılamamaktadır. Aşağıda bir tane daha implicit operator örneği paylaşıyorum.

    public class Inch
    {
        public decimal Length { get; set; }
        public static implicit operator Cm(Inch i)
        {
            Cm c = new Cm();
            c.Length = i.Length * 2.54M;
            return c;
        }
    }
    public class Cm
    {
        public decimal Length { get; set; }
        public static implicit operator Inch(Cm c)
        {
            Inch i = new Inch();
            i.Length = c.Length / 2.54M;
            return i;
        }
    }

Bu sayede aşağıdaki kodu hatasız bir şekilde çalıştırabiliriz oluyoruz.

            Inch i = new Inch();
            i.Length = 5;
            Cm cm = i;
            Console.WriteLine(cm.Length);

Implicit operator kullanımına ait güzel ve daha karmaşık bir örnek incelemek isterseniz. http://www.yazgelistir.com/Makaleler/1000002697.ygpx adresindeki makaleyi incelemenizi öneriyorum.

Şimdi isterseniz benzer örnekleri explicit operator ile ilgili örnekler yapalım. Class'larımızın aynı olduğunu düşünelim.

Yine aynı nesneleri kullandığımızı sadece karışmaması adına isimlerini değiştirdiğimizi düşünelim.

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

Yine aynı atama örneğini deneyelim.

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

Şimdi class'ımıza explicit bir operator ekleyelim.

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

 Ve atama işlemini tekrar yapmayı deneyelim ve bu satırda compiler'ın hala hata verdiğini görelim. Verdiği hata Cannot implicitly convert type 'CurrencyExplicit' to 'decimal'. An explicit conversion exists (are you missing a cast?). Burda zaten bize gerekli ipucunu söylüyor. Ben bu tipleri birbirine çeviremiyorum ama explicit bir çevrim mevcut cast etmeyi atlıyor olabilir misin şeklinde çok anlaşılır bir mesaj veriyor. O zaman biz casting'imizi yapalım.

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

 

Gördüğünüz gibi çevrim işlemini biz tanımladık ama direkt çevrime compiler izin vermedi ve bizim cast etmemizi istedi. işte bu noktada veri kayıpları olacaksa, örneğin sign değeri kaybolacaksa developer bunun farkına varabilir.

Explicit operator syntax'ına baktığınızda publIs static explicit  operator CevrilecekTip(MevcutTip) olarak bir syntax görüyorsunuz. Kullanımı oldukça basit.

Aşağıda bir tane daha explicit operator örneği paylaşıyorum. Biraz önceki örneğin aynısını yapalım.

    public class InchExplicit
    {
        public decimal Length { get; set; }
        public static explicit operator CmExplicit(InchExplicit i)
        {
            CmExplicit c = new CmExplicit();
            c.Length = i.Length * 2.54M;
            return c;
        }
    }
    public class CmExplicit
    {
        public decimal Length { get; set; }
        public static explicit operator InchExplicit(CmExplicit c)
        {
            InchExplicit i = new InchExplicit();
            i.Length = c.Length / 2.54M;
            return i;
        }
    }

Şimdi ise nasıl kullanacağımızı inceleyelim.

            InchExplicit ie = new InchExplicit();
            i.Length = 5;
            CmExplicit cme = (CmExplicit)ie;

Gördüğünüz gibi yine cast etmek gerekti.

Bu makaledeimplicit ve explicit operator'leri örneklerle incelemeye çalıştık. Umarım faydalı olmuştur.