C# Operator Overloading Kullanımı

Tüm programlama dillerinde olduğu gibi C#'ta da belli operatörler ile kolaylıkla işlemler yapılabilir. Örneğin + ile int tipindeki 2 elemanı matematiksel olarak toplayabiliriz.

    int a = 100;
    int b = 240;
    int c = a + b; // c artik 340

Görüldüğü gibi a ve b + operatörü ile matematiksel olarak toplanıp c değişkenine atandı. Peki a ve b int değilde string tipinde olsaydı?

    string a= "Hello";
    string b= " world!";
    string c = a + b; // c artik "Hello world!"

Buradan da görüldüğü gibi artık + operatörü matematiksel toplam yerine stringleri birleştirmek için kullanıldı. Yani her tip için operatörler farklı anlamlara gelebiliyor. Peki biz kendi yazdığımız tipler için +,- gibi operatörlere anlamlar kazandırabilir miyiz? Evet, Operator Overloading ile bunu yapabiliriz. Şimdi bunu nasıl gerçekleştirebiliriz bir örnek üzerinden bakalım. Point isminde bir sınıfımız olsun bu sınıf bir noktanın X,Y kordinatlarını tutyor olsun.

    public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Point(int xPos, int yPos)
        {
            X = xPos;
            Y = yPos;
        }
        public override string ToString()
        {
            return string.Format("[{0}, {1}]", this.X, this.Y);
        }
    }

Şimdi Point sınıfımızdan oluşturduğumuz p1 ve p2 nesne örneklerini + operatörü ile toplamaya çalışalım ne sonuç çıkacak?

    class Program
    {
        static void Main(string[] args)
        {
            Point p1 = new Point(10,3);
            Point p2 = new Point(7, 4);

            //p1+p2 toplamak istiyoruz
            Point p3 = p1 + p2;

            Console.WriteLine(p3);
        }
    }

Bu durumda hata alacağız. Çünkü Point sınıfımız için tanımlanmış bir + operatörü yok.

Operator '+' cannot be applied to operands of type 'OperatorOverloadingExample.Point' and 'OperatorOverloadingExample.Point'

Şimdi operatör tanımlarımız ile Point sınıfımızı yeniden tasarlayalım:

    public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Point(int xPos, int yPos)
        {
            X = xPos;
            Y = yPos;
        }
        public override string ToString()
        {
            return string.Format("[{0}, {1}]", this.X, this.Y);
        }

        //+ operatörü overload edildi
        //artık + ile 2 point nesnesinin X,Y değerleri toplanıp
        //yeni bir Point nesnesi döndürüyor
        public static Point operator + (Point p1, Point p2)
        {
            return new Point(p1.X + p2.Y, p1.Y + p2.X);
        }

        //+ operatörü overload edildi
        //artık + ile 2 point nesnesinin X,Y değerleri çıkarılıp
        //yeni bir Point nesnesi döndürüyor
        public static Point operator - (Point p1, Point p2)
        {
            return new Point(p1.X- p2.X, p1.Y -p2.Y);
        }
    }

Gördüğünüz gibi artık + ve - operatörlerini Point sınıfımız için tanımladık artık programımız hata almadan çalışaktır. + operatörü artık gönderilen 2 point nesnesinin X ve Y koordinatlarını toplayıp yeni bir Point nesnesi döndürüyor. - operatörü ise gönderilen 2 point nesnesinin X ve Y koordinatlarını çıkartıp yeni bir Point nesnesi döndürüyor.

Bu durumda programımızın çıktısı şöyle olacaktır:


Farklı olarak şu şekilde operatörler ekleyebiliriz sınıfımıza:

        // artik Point p2 = p1+5; şeklinde tanımlama yapılabilir.        
        public static Point operator +(Point p1, int change)
        {
            return new Point(p1.X + change, p1.Y + change);
        }
        //artik ++p1 şeklinde tanımlama yapilabilir.
        public static Point operator ++(Point p1)
        {
            return new Point(p1.X + 1, p1.Y + 1);
        }
        //ÖNEMLİ "=" operatörü bu şekilde override edilir
        public override bool Equals(object o)
        {
            return o.ToString() == this.ToString();
        }

        //artik p1==p2 kontrolu yapilabilir
        public static bool operator ==(Point p1, Point p2)
        {
            return p1.Equals(p2);
        }
        //artik p1!=p2 kontrolu yapilabilir
        public static bool operator !=(Point p1, Point p2)
        {
            return !p1.Equals(p2);
        }
        
Peki -=, += gibi operatörlerini kullanmak için ne yapmamız lazım? Bunlar için ekstra bişi yapmamıza gerek yok bu operatörleri + ve - operatörlerini tanımladıysak kullanabiliriz.

Şimdi birde <,> büyük küçük kontrollerini nasıl override edebiliriz ona bakalım:

    
   public class Point : IComparable<Point>
    {
        //..
        public int CompareTo(Point other)
        {
            if (this.X > other.X && this.Y > other.Y)
                return 1;
            if (this.X < other.X && this.Y < other.Y)
                return -1;
            else
                return 0;
        }
        public static bool operator <(Point p1, Point p2)
        { return (p1.CompareTo(p2) < 0); }
        public static bool operator >(Point p1, Point p2)
        { return (p1.CompareTo(p2) > 0); }
        public static bool operator <=(Point p1, Point p2)
        { return (p1.CompareTo(p2) <= 0); }
        public static bool operator >=(Point p1, Point p2)
        { return (p1.CompareTo(p2) >= 0); }
    }

Override Edilebilen Operatörler:

Unary Operators : +, -,! , ~, ++, --, true, false
Binary Operators : +, -, *, /, %, &, |, ^, <<, >>
Comparison Operators : ==,!=, <, >, <=, >=

Override Edilemeyen Operatörler:

The [] Operator : []
The () Operator :()

Örnek Proje:
OperatorOverloadingExample.rar

0 yorum :

Yorum Gönder