Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

C#’ta Operatör Aşırı Yükleme(Operator Overloading)

Merhaba,

Bunca yıldır C# üzerinde syntax yapısı ve OOP ile ilgili bir çok makale ele almış bulunmaktayım. Her ne kadar tüm konulara değinmek için çaba harcasamda mevcut platform gereği(blog) önem arz eden ve genel geçer kullanışlılığa sahip yapıları tanıtma gereği duymaktayım. Hal böyle olunca aylarca aklımda olan ama bir türlü oturupta üzerinde makale derleyecek vakti yaratamadığım bir o kadar da konu var ki işte Operator Overloading onlardan biri… Artık C#’ın bu güzel ve köklü nimetlerine kendi bloğumda yer verme zamanı geldiğini düşünüyorum.

C# yapısal olarak çok güzel ve güçlü bir dil olmakla beraber her geçen gün gücüne güç katmakta, kendini geliştirerek yenilemektedir. Doğal olarak bu potansiyel dilin mekaniğine yansımakta ve biz yazılımcıların dil seçimindeki en büyük tercihi bu potansiyel sırda aranmaktadır.

Bana sorarsanız C# dilinin bu potansiyel gücünün en mühim yapıları arasında sınıflarda oluşturulabilen kendine has yapılardan operatör metotları bulunmaktadır.

Ne mi bu operatör metotları?

Biliyorsunuz ki, programlamada birden fazla değer arasında bağıntı oluşturduğumuz sembollere operatör demekteyiz. Bu operatörler genel olarak kullandığımız birden fazla sayı arasında matematiksel işlem yapan aritmatik operatörler(+, -, /, *), birden fazla değer arasında karşılaştırma yapan karşılaştırma operatörleri(<, >, <=, >=, ==, !=), şart – koşul yapılarında kullandığımız mantıksal operatörler(&, &&, |, ||, !, ^) ve yerine göre bunların dışında kullandığımız niceleri değerler arası görüldüğü üzere işlem yapmaktadırlar.

Örnek olarak 2 + 5 şeklinde tanımlanan bir ifade programatik açıdan ele alındığında 7 sonucunu verecektir. Çünkü “+” operatörü verilen iki sayısal değer arasında bir matematiksel toplama işlemi yapmakla görevlendirilmiştir. Benzer şekilde bu görevlendirme diğer matematik sembolleri içinde geçerlidir. Aslında bu işlevler sayısal değerlere özel bir operator overloading yapıldığı için gerçekleştirilmektedir. Buradan şu sonucu çıkarabilir ki; sayısal değerlerde olduğu gibi görevi mimarisel olarak belirlenmiş operatörlerin tiplerine bizler tekrardan operator overloading işlemi yapamamaktayız.

Peki… + operatörünü yeniden ele alırsak eğer, iki sayısal değer arasına + operatörünü koyarsak matematiksel toplama işlemi yapıyordu. Peki kendi oluşturduğumuz herhangi bir sınıfın nesneleri yahut nesnelerini işaretleyen referansları arasında + operatörünü kullanırsak ne olacak?

    class Program
    {
        static void Main(string[] args)
        {
            MyClass m1 = new MyClass();
            MyClass m2 = new MyClass();
            m1 + m2;
        }
    }

    class MyClass
    {

    }

İşte şu düzeyde bu tarz bir kullanımdan hata alınacaktır. Nihayetinde + operatörünün kendi oluşturmuş olduğumuz MyClass isimli sınıf için bir işlevselliğini tanımlamadığımızdan dolayı yukarıdaki çalışmada operatör iki nesne arasında nasıl bir işlevde bulunacağını bilememektedir. İşte biz örnekteki MyCLass misali kendi oluşturmuş olduğumuz sınıflarımız için herhangi bir operatöre overload uygulayabilecek ve ilgili operatöre ilgili sınıf üzerindeki kullanışılında farklı bir işlevsellik yükleyeceğiz.

Tabi bu işlemi yapmadan önce değinmek istediğim bir husus mevcuttur.

Biliyorsunuz ki, string tipi değer tipli gibi ifade edilebilen ama aslen referans özellikli bir tiptir. Referans type olan bu string tipinde birden fazla string ifadeler arasında + operatörünü kullanırsak eğer string ifadeleri yan yana birleştirmektedir.

            string Ad = "Gençay";
            string SoyAd = "Yıldız";
            string AdSoyad = Ad + " " + SoyAd;

Görüldüğü üzere Ad ve SoyAd değişkenleri arasında + operatörü kullanıldığı vakit tekrardan string bir sonuç elde edilmektedir.

Peki compiler bu işlemi nasıl ele almaktadır?

Derleme işlemi esnasında compiler sınıf yapıları üzerinde operatör kullanıldığını gördüğü vakit ilgili sınıf içerisinde operator+ isimli metodu arayacaktır. Eğer ki bu metodu bulamazsa hata verecektir. Söz konusu sınıfımız String sınıfı olduğu için arayacağı metot aynen şu şekilde olacaktır.

String.operator+(a, b);

Dikkat ederseniz aranan operator+ metoduna ilgili sınıfın ismi üzerinden erişilmektedir. Yani buradan operatör metotlarının static yapıda olacağını çıkarıyoruz.

Şimdi kendi oluşturmuş olduğumuz bir sınıfa operatör yüklemeye değinmeye bir adım kala operator overloading işlemi için dikkat edilmesi gereken kurallara ve kısıtlamalara değinelim.

  • Operatör metotları static olarak tanımlanmalıdır.
  • Operatör metotlarının isimleri operator keywordü ile birlikte kullanılacak operatörün sembolü verilerek belirlenir.

    operator+, operatör*, opreator<= vs. gibi...

  • Operatör metotlarının en az bir parametresi olmalıdır.
  • Operatör metotlarıda normal metotlar gibi çoklu yüklenebilir.
  • Tekil(Unary) operatör metotlarında parametre mutlaka ilgili sınıf türünden olmalıdır. Binary(iki operand alan) operatör metotlarından ise en az bir parametre ilgili sınıf türünden olmalıdır.
  • Operatör metotları ref ve out anahtar sözcüklerinden parametre alamazlar.
  • +=, -=, /= ve *= operatörlerinin aşırı yüklenmeleri olmamaktadır. İlgili operatörlerin kullanımları durumunda direkt olarak assign(=) operatörü olmayan karşılığını tetiklemektedir.

    Örnek x += b durumu operator+ metodunu tetikleyecektir.

  • Operatörlerin öncelik sırası değişmez.
  • Temel veri türleri için operatörleri yeniden yükleyemeyiz.
  • &&, ||, [], (), =, ?, ., ?:, ->, is, sizeof, new ve typeof gibi operatörlere aşırı yükleme yapılamaz.

Evet… Şimdi aşağıdaki gibi kendi oluşturmuş olduğumuz bir sınıfta operatörleri aşırı yükleyelim.

    class Dunya
    {
        public int Cap { get; set; }
        public static Dunya operator +(Dunya d1, Dunya d2) => new Dunya { Cap = d1.Cap + d2.Cap };
        public static string operator -(Dunya d1, Dunya d2) => (d1.Cap - d2.Cap).ToString();
        public static Dunya operator /(Dunya d1, int d2) => new Dunya { Cap = d1.Cap / d2 };
        public static decimal operator *(Dunya d1, int d2) => d1.Cap * d2;
    }

Bu operatörlerin kullanımı aşağıdaki gibidir.

    class Program
    {
        static void Main(string[] args)
        {
            Dunya d1 = new Dunya() { Cap = 36 };
            Dunya d2 = new Dunya() { Cap = 18 };

            Dunya Topla = d1 + d2;
            Console.WriteLine(Topla.Cap);

            string Cikar = d1 - d2;
            Console.WriteLine(Cikar);

            Dunya Bol = d1 / 120;
            Console.WriteLine(Bol.Cap);

            decimal Carp = d1 * 120;
            Console.WriteLine(Carp);

            Console.Read();
        }
    }

C#'ta Operatör Aşırı Yükleme(Operator Overloading)

Gördüğünüz gibi oluşturmuş olduğumuz sınıflara özel operatörlerin nasıl çoklu yüklendiğini incelemiş olduk. Sonraki yazılarımızda dönüşüm operatörleri olan implicit(istemsiz/kapalı) ve explicit(istemli/açık) operatörlerinin aşırı yüklenmesini inceleyeceğiz.

Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. Bahadır dedi ki:

    2 yıl önce başlamıştım c# öğrenmeye şuan keşke 2 yıl öncede böyle bir kaynak olsaydı diyorum. Bu bilgileri ilk defa öğreniyorum böyle bir Türkçe kaynağın olması beni çok mutlu etti çok teşekkür ederim.

    • Gençay dedi ki:

      Merhaba Bahadır;

      Aslında Türkçe kaynak olarak internet dışında bu bilgilere sahip olabileceğin birçok kaynak mevcuttur. Çoğu kitap bu ve bunun gibi bilgileri ileri düzey başlığı altında değerlendirmektedir. Bu konuda örnek olarak Sefer Algan’ın kitabını tavsiye ederim.

      Bu arada güzel yaklaşımın için teşekkür ederim.
      Sevgilerimle…

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir