C# Implicit, Explicit Conversions Kullanımı

Programlarınızı yazarken bir çok kez bir tipten diğer tipe çevirim yapmışsınızdır. Bu çevrimlere örnek verirsek long tipinden int tipine, object tipinden string tipine gibi. Bu çevrimler sırasında daha geniş olan örneğin long'tan int'e çevrim yaparken data kaybı yaşanabilir. Ama int'i long'a çevririsek bu data kaybı yaşanmaz.



Data kaybı yaşanmayan çevrim Implicit, data kaybı yaşanabilecek çevrim ise Explicit olarak adlandırabiliriz. Implicit Conversation aritmetik operatörler ile yapılır bir cast operatörü içermez. Explicit Conversation ise cast operatörü ile yapılan coversion işlemidir.

            int a = 123;
            long b = a; // Implicit conversion from int to long.
            int c = (int)b; // Explicit conversion from long to int.

Aynı zamanda custom sınıflarımız içerisinde Base, Derived ilişkisi içerisinde bu çevrimler yapılabilir.
    class Base { }
    class Derived : Base { }
    class Program
    {
        static void Main(string[] args)
        {
            // Implicit: derived to base.
            Base myBaseType;
            myBaseType = new Derived();
            // Must explicitly cast to store base reference
            // in derived type.
            Derived myDerivedType = (Derived)myBaseType;
        }
    }

Peki custom sınıflarımız arasında Base, Derived ilişkisi olmadığı halde iki farklı sınıf önerğini birbirlerine çevirmek istesek ne yapacağız? Örnek biraz saçma olsada öğrenmek için veriyorum. Dikdörtgen ve Cember sınıflarımız olsun. Dikdörtgen'i cembere çevirmek istiyoruz.

    public struct Square
    {
        public int Length { get; set; }
        public Square(int l)
            : this()
        {
            Length = l;
        }
        public void Draw()
        {
            for (int i = 0; i < Length; i++)
            {
                for (int j = 0; j < Length; j++)
                {
                    Console.Write("*");
                }
                Console.WriteLine();
            }
        }
        public override string ToString()
        { return string.Format("[Length = {0}]", Length); }
    }
    public struct Rectangle
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public Rectangle(int w, int h)
            : this()
        {
            Width = w; Height = h;
        }
        public void Draw()
        {
            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    Console.Write("*");
                }
                Console.WriteLine();
            }
        }
        public override string ToString()
        {
            return string.Format("[Width = {0}; Height = {1}]",
            Width, Height);
        }
    }

Rectangle ve Square adında 2 struct yapısı tanımladık. Şimdi bu 2 yapı arasında şöyle bir çevrim yapmak istesek:

            Rectangle r = new Rectangle(15, 4);
            Square s = (Square)r;

Rectangle nesnesini Square nesnesine çevirmeye çalıştık. Fakat bu 2 nesne arasında Base, Derived ilişkisi oladığı için aşağıdaki hatayı alacağız:

Cannot convert type 'CustomTypeConversions.Rectangle' to 'CustomTypeConversions.Square'
Compiler bize Rectangle'ı Square'e çeviremediğini belirten bir hata mesajı verdi. Peki bunu custom bir şekilde nasıl yapabiliriz şimdi buna bakalım. C#'ta custom çevrim işlemleri için kullanılan explicitimplicit keywordleri vardır.

Yukarıdaki çevrim explicit bir çevrim olduğu için explicit keywordunu şu şekilde kullanarak hata almadan çevrim işlemini gerçekleştirebiliriz. Aşağıdaki kodu Square sınıfımıza eklersek:

        // Explicit: Rectangle'in Height propertysini kullanarak
        // Square olusturuyor
        public static explicit operator Square(Rectangle r)
        {
            Square s = new Square();
            s.Length = r.Height;
            return s;
        }

Artık
            Rectangle r = new Rectangle(15, 4);
            Square s = (Square)r;

Bu kod hatasız bir şekilde çalışacak ve r Rectangle nesnesinin Height property değeri olan 4'u kullanarak Length'i 4 olan bir squere nesnesi çevrimi yapılacaktır. Gördüğünüz gibi explicit olarak Rectangle nesnesinden Square nesnesine çevrimi gerçekleştirdik.

Aşağıdaki gibi istediğiniz gibi farklı çevrimlerde yazabilirsiniz:

        // int tipini Square nesnesine çevirir
        // Example: Square s = (Square)90;
        public static explicit operator Square( int sideLength )
        {
            Square newSq = new Square();
            newSq.Length = sideLength;
            return newSq;
        }

        // Square nesnesini int tipini çevirir
        // Example: int a = (Square)s;
        public static explicit operator int( Square s )
        { return s.Length; }

Peki şöyle bir çevrim yapmak istesek ne olacak?

            Square s3 = new Square();
            s3.Length = 83;

            // implicit cevrim
            Rectangle rect2 = s3;

Bu durumda compiler yine hata verecektir. Çünkü yapmaya çalıştığımız çevrim implicit fakat biz Rectangle sınıfımıza implicit çevrimi nasıl yapacağını belirten bir şey yazmadık.

Cannot implicitly convert type 'CustomTypeConversions.Square' to 'CustomTypeConversions.Rectangle'
implicit işlemini yapmak için implicit keyword'ünü kullanarak sınıfımıza bu çevrimi nasıl yapacağını söylememiz gerekiyor. Aşağıdaki kodu Recangle sınıfımıza eklersek:

        // implicit cevrim Square to Rectangle
        public static implicit operator Rectangle(Square s)
        {
            return new Rectangle(s.Length + 10, s.Length + 5);
        }
Artık

            Square s3 = new Square();
            s3.Length = 83;

            // implicit cevrim
            Rectangle rect2 = s3;

Bu kod hata almadan çalışacaktır. Bu şekilde implicit şekilde Squere nesnemizi Rectangle nesnemize çevirmeyi başardık.

Örnek Proje:
CustomTypeConversions.rar

0 yorum :

Yorum Gönder