C#nedir?com
 
YAZAR HAKKINDA
Umut Ozkan
Umut Ozkan
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
2 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: aritmetik degerlerini explicit kasiyer operator otobus overload override public return sayisi static string tanimli tipler C# / VC#/.NET Umut Ozkan
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Orta
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 25.7.2007
Okunma Sayısı : 39772
Yorum Sayısı : 1     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
XML - Deniz Kılınç
emre TAŞ
yazının devamı >
emre TAŞ
Decompiling and Reverse Engineering .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
Masaüstü mü ? İnternet Mi? .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
.Net Kavramları - .Net Radyo
emre TAŞ
yazının devamı >
emre TAŞ
Yeni Başlayanlar için - .Net Radyo
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 10.8.2020
Turhal Temizer
Mac OS/X Removing CUDA 10.8.2020
Burak Selim Şenyurt
Sekiz Saatlik Sonsuz Döngü 10.8.2020
Burak Selim Şenyurt
Switch Case Kullanmadan Kod Yazılabilir mi? 10.8.2020
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
Detayları ile Operatörleri Aşırı Yüklemek (Operator Overloading)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Hepimizin bildiği gibi operatörler, tipler arasında çeşitli işlemler yapan işaretlerdir.Aritmetik Operatörler,Mantıksal Operatörler gibi kendi aralarında gruplara ayrılmışlardır.Aritmetik operatörlerden konuşmak gerekirse; “+” operatörünün varsayılan davranışı verilen iki değerin aritmetik toplamını almaktır.Mantıksal operatörlerden bir örnek vermek gerekirse; “<” operatörünün varsayılan görevi işaretin sol tarafındaki değerin sağ tarafındaki değere göre küçük olup olmadığını denetlemektir.

//+ operatörünün int tipi için üstlendiği eylem.
int a = 10;
int b = 50;
int c = a + b; // c nin değeri 60’dır.
Sayısal ifadeler için “+” aritmetik operatörünün üstlendiği görev toplama işlemi yapmak iken, DateTime ve TimeSpan ifadelerde bu görev tamamen farklı bir hal alır.

// + operatörünün DateTime tipi için üstlendiği eylem.
DateTime dt = new DateTime(2007, 12, 12);
DateTime dt1 = new DateTime(2006, 12, 12);
TimeSpan ts = dt - dt1;
DateTime top = dt + ts;
Console.WriteLine(top);
Yukarıda da görüldüğü üzere + operatörünün davranışı int tipler için farklı, DateTime tipler için farklıdır. DateTime yapısı(struct) içinde + operatörüne yeni bir davranış biçimi olan tarihle, tarih farkını birleştirme görevi aşırı yüklenmiştir(overload).

gotodef



//DateTime struct’ının metadatasında görülen operatör aşırı yükleme (operator overloading) Bizde eğer operatörlerle kullanılabilir tipler yazmak istersek(class veya struct); bu tiplere operatörlerle kullanıldıklarında yapacakları işi ögretmemiz yani operatörleri aşırı yüklememiz (operatör overloading) gerekmektedir. Örnek bir senaryo üzerinden hareket edelim. Söz gelimi bir firma sahibi, kasiyerlerinin toplam ne kadar ürün sattığını öğrenmek istiyor olsun. Bunun için işe Kasiyer isimli bir sınıfı(class) oluşturarak başlayalım.

using System;
using System.Collections.Generic;
using System.Text;

namespace OperatörOverloading
{
    class Kasiyer
    {
        //iki adet field tanımlayalım.
        int _satisAdet;
        string _calisanAdi;
        //yapıcı metotumuzda (constructor) degerlerini sınıfı kullanan kullanıcıdan alalım.
        public Kasiyer(string calisanAdi,int sattigiUrunAdet)
        {
            _calisanAdi = calisanAdi;
            _satisAdet = sattigiUrunAdet;
        }
        //ve bilgi almak istedigimizde bize yardımcı olması adına object sınıfının virtual olarak isaretlenmis ToString() metotunu (override) ezelim.
        public override string ToString()
        {
            return string.Format("{0} {1} adet satis",_calisanAdi,_satisAdet);
        }
    }
}
Kasiyer sınıfımızı(class) oluşturduk. Şimdide gelin sınıfımızı örnekledikten sonra kullanacak olan program.cs dosyasını aşağıdaki kod parçasında olduğu gibi oluşturalım.

using System;
using System.Collections.Generic;
using System.Text;

namespace OperatörOverloading
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("***Operatörleri Aşırı Yükleyelim***\n");
            //ksyr sınıfından iki farklı nesne olusturduk.Satis degerlerini 30 ve 35 olarak belirledik.
            Kasiyer ksyrHasan = new Kasiyer("Hasan", 30);
            Kasiyer ksyrAyten = new Kasiyer("Ayten", 35);
            Console.WriteLine(ksyrAyten.ToString());
            Console.WriteLine(ksyrHasan);
            //Error 1 Operatör ’+’ cannot be applied to operands of type ’OperatörOverloading.Kasiyer’ and ’OperatörOverloading.Kasiyer’ D:\Work\testing\OperatörOverloading\OperatörOverloading\Program.cs 36 42 OperatörOverloading
            Kasiyer ksyrlerToplamSatis = ksyrHasan + ksyrAyten;
        }
    }
}
Oluşturduğumuz kasiyer tipinden nesne örneklerini (ksyrHasan,ksyrAyten) herhangi bir operatörle kullanmaya çalıştığımız taktirde bu iki tipi bu operatörle kullanamayacağımızı belirten bir hata mesajını derleme zamanında alırız. Bunun sebebi kullandığımız operatörün bu iki tiple kullanıldığında ne gibi bir eylemde bulunacağını bilmemesinden kaynaklanmaktadır. Toplama operatörünün Kasiyer nesne örnekleri üzerinde kullanılmasını sağlamak için gelin bu operatörü aşırı yükleyelim ve artık ne iş yapacağını bilsin!.

Yapılan son güncellemeden sonra Kasiyer Sınıfı:

using System;
using System.Collections.Generic;
using System.Text;

namespace OperatörOverloading
{
    class Kasiyer
    {
        //iki adet field tanımlayalım.
        int _satisAdet;
        string _calisanAdi;
        //yapıcı metotumuzda (constructior) degerlerini sınıfı kullanan kullanıcıdan alalım.
        public Kasiyer(string calisanAdi,int sattigiUrunAdet)
        {
            _calisanAdi = calisanAdi;
            _satisAdet = sattigiUrunAdet;
        }
        //ve bilgi almak istedigimizde bize yardımcı olması adına object sınıfının virtual olarak isaretlenmis ToString() metotunu (override) ezelim.
        public override string ToString()
        {
            return string.Format("{0} {1} adet satis",_calisanAdi,_satisAdet);
        }
        //En az bir Parametre Sınıf tipinden olmalı.
        public static Kasiyer operator +(Kasiyer ks1,Kasiyer ks2)
        {
            int toplamSatis = ks1._satisAdet + ks2._satisAdet;
            return new Kasiyer("toplam", toplamSatis);
        }
    }   
}
Operatörleri overload ederken bir takım kısıtlamalar vardır. Şimdi biraz bunlardan bahsedelim.

  • Operatör overload metotlarında erişim belirleyicisi olarak sadece public kullanılmalıdır. Sınıfın nesne örnekleri heryerde operatörlerle kullanılmak istenebilir. Bu yüzden de mantıklı olanı public olmasıdır.
  • Operatör overload metotlarda niteleyici mutlaka static olmalıdır. Static olmasının sebebi metotun çağrılabilmesi (invoke) için herhangi bir nesne örneğine ihtiyacının olmaması  ve nesne örneklerinden nesne örneklerine yapılacak işlemin değişmemesidir. Yani toplama işlemini nasıl yapacağını bir kere öğrenmesi yeterlidir. Her nesne örneğinde tekrar öğrenmesine gerek yoktur. (Bkz : “Statik Olmak” ).
  • Operatör overload metotlarda parametre sayısı iki adet olmalıdır (bilinçli/bilinçsiz atama operatörleri hariç) ve bunlardan bir tanesi mutlaka operatörü overload ettiğimiz sınıf tipinden olmalıdır.(diğer parametre sistemde tanımlı tiplerden birisi yada kendi yazdığımız tiplerden birisi olabilir.)
  • Geri dönüş tipi iş mantığımıza göre herhangi anlamlı bir tip olabilir. Örnek senaryoda kasiyerlerin sattıkları ürün toplamlarını taşıyan yeni bir Kasiyer sınıfı nesne örneği geriye döndürülmektedir. Elbetteki istenirse uygun ve anlamlı olan başka tiplerde dönüş değeri olarak göz önüne alınabilir.
“Operatör Overload metotlarıda”, overload edilebilir. Operatör,"Kasiyer+tip" şeklinde kullanıldığında tip alanı için gelecek tipe göre en uygun metotu tercih edecektir.(Pointy geliştirici tarafından yazılmış örnek bir sınıftır)

public static Kasiyer operatör +(Kasiyer ks1,Kasiyer ks2)
{
    int toplamSatis = ks1._satisAdet + ks2._satisAdet;
    return new Kasiyer("toplam", toplamSatis);
}
public static Kasiyer operatör +(Kasiyer ks1, Pointy p)
{
    int toplamSatis = ks1._satisAdet + p.x;
    return new Kasiyer("toplam", toplamSatis);
}
public static int operator +(Kasiyer ks1, int a)
{
    int toplamSatis = ks1._satisAdet + a;
    return toplamSatis;
}

uyari   Operatör Overload metotların geri dönüş tipi void olamaz!
Program.cs dosyamıza geri dönelim ve uygulamamızı tekrar çalıştırmayı deneyelim.

using System;
using System.Collections.Generic;
using System.Text;

namespace OperatörOverloading
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("***Operatörleri Aşırı Yükleyelim***\n");
            //ksyr sınıfından iki farklı nesne olusturduk.Satis degerlerini 30 ve 35 olarak belirledik.
            Kasiyer ksyrHasan = new Kasiyer("Hasan", 30);
            Kasiyer ksyrAyten = new Kasiyer("Ayten", 35);
            Console.WriteLine(ksyrAyten.ToString());
            Console.WriteLine(ksyrHasan);
            Kasiyer ksyrlerToplamSatis = ksyrHasan + ksyrAyten;
            //To.String() metotunu Kasiyer sınıfında override ettigimiz için Console.WriteLine override metot içindeki string ifadeyi yazacaktır.
            //son duruma bakalım?
            Console.WriteLine(ksyrlerToplamSatis);
        }
    }
}



Hiçbir derleme zamanı hatası almadık. Çünkü Kasiyer sınıfı nesne örnekleri ile birlikte kullandığımız operatör artık bu nesne örnekleri ile kullanıldığında ne gibi bir işlem yapacağını Kasiyer sınıfı içerisinde tanımlanan, operatör + anahtar sözcüklerini yapısında barındıran metot sayesinde bilmektedir.
 



uyari Kasiyer ksyrlerToplamSatis = ksyrHasan + ksyrAyten;

Satırında aslında arka tarafta bilinçsiz (implicitly) olarak gizlice

Kasiyer ksyrlerToplamSatis= Kasiyer.operatör +( ksyrHasan,ksyrAyten); şeklinde metot çagrımı yapılmaktadır.

 

AŞIRI YÜKLENEBİLİR OPERATÖRLER (OVERLOADABLE OPERATORS)


C# Operatör

Yükelenebilite

+, –, !, ~, ++, – –, true, false

Aşırı yüklenebilirler.

+, –, *, /, %, &, |, ^, <<, >>

Aşırı yüklenebilirler.

==, !=, <, >, <=, >=

Aşırı yüklenebilirler.

[]

Aşırı yüklenemez.(indexer sayesinde fonksiyonalite kazanabilir)

()

Aşırı yüklenemez.

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

Binary ve Aritmetik operatörlerle kullanılan atama operatörleri binary veya aritmetik operatörler aşırı yüklendiği taktirde kullanılabilirler.


uyari Binary ve Aritmetik operatörlerle kullanılan atama operatörleri (+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=), binary ve aritmetik operatörler aşırı yüklendiğinde kullanılabilirler.
 
ksyrHasan += ksyrAyten;
Console.WriteLine(ksyrHasan);
Diğer operatörlerede şöyle bir bakalım;Mantıksal operatörleri tek başına aşırı yükeleyemeyiz. Çift olarak ele almamız gerekir. Eğer ==,<,<= operatörlerinden birini aşırı yüklemek istersek !=,>,>= operatörlerinden ilgili operatörüde aşırı yüklememiz gerekir.

Mantıksal operatörler bool değer döndürecek şekilde aşırı yüklenirler. Zaten mantıklı olanda budur. Fakat diğer tipleri döndürme konusunda herhangi bir kısıtlama getirilmemiştir.

public static bool operator <(Kasiyer k1, Kasiyer k2)
{
//kod bloğu
}


Mantıksal operatörler aşırı yüklenirken işleri kolaylaştırmak için bir takım metotlardan faydalanabiliriz. Bunlardan == ve != için konuşmak gerekirse object sınıfının virtual olarak işaretlenmiş Equals metodunu override etmek bu operatörleri aşırı yüklerken oldukça işimize yarayacaktır.



 

public override bool Equals(object obj)
{
Kasiyer k1 = (Kasiyer)obj;
if (k1._calisanAdi == this._calisanAdi && k1._satisAdet==this._satisAdet)
{
    return true;
}
    return false;
}
public static bool operator ==(Kasiyer k1, Kasiyer k2)
{
    return k1.Equals(k2);
}
public static bool operator !=(Kasiyer k1, Kasiyer k2)
{
    return !(k1.Equals(k2));
}
Şimdi de “>” ve “<” operatörlerine bakalım. Bu operatörleri aşırı yüklemede bize yardımcı olması için IComparable veya .Net 2.0 la birlikte gelen generic IComparable<> arayüzünü uyarlayabiliriz (Interface Implementation).

using System;
using System.Collections.Generic;
using System.Text;

namespace OperatörOverloading
{
    class Kasiyer:IComparable<Kasiyer>
    {
        #region IComparable<Kasiyer> Members
        //CompareTo metotu nesneAdi.CompareTo(karsilastirilacakNesne) seklinde kullanılır.Eger nesneAdi karsilastirilacak nesneden büyükse 1,küçükse -1,eşitse 0         dondurur.
        public int CompareTo(Kasiyer other)
        {
            if (this._satisAdet > other._satisAdet)
            {
                return 1;
            }
            else if (this._satisAdet < other._satisAdet)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
        #endregion
        public static bool operator <(Kasiyer k1, Kasiyer k2)
        {
            return k1.CompareTo(k2) < 0;
        }
        public static bool operator >(Kasiyer k1, Kasiyer k2)
        {
            return k1.CompareTo(k2) > 0;
        }
    }
}
IComparable<> generic interface’ini implement edip CompareTo metotunu kodladıktan sonra artık “<” ve “>” operatörlerini aşırı yüklemek için artık ekstra efor sarfetmemiz gerekmiyor. İlk operatör overloading metot için konusmak gerekirse;k1.CompareTo(k2) ifadesinden eger k1 küçükse -1 donecektir. ifadenin sağında ise < 0 bulunmaktadır ve k1’in küçük olma durumunda dönecek değer true olacaktır. Acaba overload edilen operatörlerimiz CIL kodunda nasıl yer alıyor. Visual Studio Command Promt vasıtasıyla ildasm.exe aracımızı açıp uygulamamızın CIL kodunu inceleyelim şimdide.

IL

Her bir overload edilmiş operatör metotu CIL tarafında özel isimler verilerek adlandırılır.

uyari .method public hidebysig specialname static

        bool  op_GreaterThan(valuetype OperatörOverloading.Pointy po,

                        valuetype OperatörOverloading.Pointy p1) cil managed

   Büyüktur (>) operatöru overload metotunun CIL görünümü.
En çok kullanılar operatörlerin overload metotlarının CIL deki özel isimleri aşağıdaki tabloda verilmiştir.

C# Operatör

CIL Karşılığı

––

++

+



*

/

==

>

<

!=

>=

<=

–=

+=

op_Decrement()

op_Increment()

op_Addition()

op_Subtraction()

op_Multiply()

op_Division()

op_Equality()

op_GreaterThan()

op_LessThan()

op_Inequality()

op_GreaterThanOrEqual()

op_LessThanOrEqual()

op_SubtractionAssignment()

op_AdditionAssignment()
Kullanıcı Tanımlı Tip Dönüşümleri(Implicit,Explicit)

Aşırı yükleyebileceğimiz operatörler sadece yukarıda bahsedilen operatörlerden ibaret değildir.Operatör aşırı yükleyerek Explicit (bilinçli) ve Implicit (bilinçsiz) tür dönüşümleri de ele alınabilir. Kısaca bilinçli ve bilinçsiz tür dönüşümlerinin neler olduklarını hatırlayalım. Bilinçli(Explicitly) tür dönüşümleri küçük bir veri tipinde büyük bir veritipinin değerini saklamak istediğimizde gerekir. C# tip güvenliğine önem verdiği için böyle bir dönüşüme bilinçsiz(Implicitly) olarak izin vermeyecektir. Çünkü böyle bir durumda olası bir veri kaybı yaşanabilir. Bu yüzden bizden ne yaptığımızı bildiğimizi onaylamamızı isteyecektir. Bu onaylamayı Cast operatörü ile yaparak  derleyiciye “Ben ne yaptığımın farkındayım” demiş oluyoruz.

//Explicitly tür dönüşümü ve cast operatörunun kullanımı
long büyükSayi = 45;
int sayi = (int) büyükSayi;
Implicitly tür dönüşümleri ise küçük tipin büyük tipe atandığı durumlardır. Bu nedenle daha güvenli dönüşümlerdir ve herhangi bir cast işlemine gerek duymaz.

//Implicitly tür dönüşümü
int sayi2 = 5;
long büyükSayi = sayi2;
Kendi yazdığımız tiplerimizde bu dönüşümlerin nası uygulandıklarını görmek için iki adet Minibus(küçük tipi temsil etsin) ve Otobus (büyük tipi temsil etsin) isimli struct yazalım.

using System;
using System.Collections.Generic;
using System.Text;
namespace ImplicitExplicitOpOv
{
    struct Otobus
    {
        public int koltukSayisi;
        public int ayakta;
        public void YolcuDoldur()
        {
            Console.WriteLine("yolcular otobuse dolduruldu");
        }
        public override string ToString()
        {
            return string.Format("koltuk sayısı {0} ayakta yolcu sayısı {1}", koltukSayisi, ayakta);
        }
    }
    struct Minibus
    {
        public int koltukSayisi;
        public int ayakta;
        public void YolcuDoldur()
        {
            Console.WriteLine("yolcular Minibuse dolduruldu");
        }
        public override string ToString()
        {
            return string.Format("koltuk sayısı {0} ayakta yolcu sayısı {1}", koltukSayisi, ayakta);
        }
    }
}
Şimdide bu yapıları (struct) kullanacak Program.cs dosyamızı inceleyelim.

using System;
using System.Collections.Generic;
using System.Text;

namespace ImplicitExplicitOpOv
{
    class Program
    {
        static void Main(string[] args)
        {
            //büyük olan tipimizi tanımlayalım ve degerlerini verelim.
            Otobus ikarus = new Otobus();
            ikarus.ayakta = 120;
            ikarus.koltukSayisi = 60;
            //küçük olan tipimizi tanımlayalım ve degerlerini verelim.
            Minibus deutz = new Minibus();
            deutz.ayakta = 15;
            deutz.koltukSayisi=25;

            //Error 1 Cannot implicitly convert type ’ImplicitExplicitOpOv.Minibus’ to ’ImplicitExplicitOpOv.Otobus’ D:\Work\testing\OperatörOverloading\ImplicitExplicitOpOv\Program.cs 19 22 ImplicitExplicitOpOv

            //küçük tipi büyük tipe atmaya calıstıgımızda yukardaki hatayı alıyoruz...
            ikarus = deutz;
        }
    }
}

Implicitly bir dönüşüm yapmak istediğimizde böyle bir hata alıyoruz. Şimdi de cast işlemi (explicitly tür dönüşümü) yaparak tekrar deneyelim.

// Error    1     Cannot convert type ’ImplicitExplicitOpOv.Minibus’ to ’ImplicitExplicitOpOv.Otobus’ D:\Work\testing\OperatörOverloading\ImplicitExplicitOpOv\Program.cs    26    22      ImplicitExplicitOpOv
           deutz = (Minibus)ikarus;
Explicitly tür dönüşümü yaptığımız taktirdede yukarıda görülen hatayı alırız. O zaman yapmamız gereken yazdığımız bu tiplere tip dönüşümlerini öğretmektir. Yapacağımız işlemler hemen hemen yukarıda yaptığımız Aritmetik ve Mantıksal operatör yüklemelerindekine benzer işlemler olacaktır. Buna göre Otobus ve Minibus yapılarındaki(structs) ilgili güncellemeler aşağıdaki gibidir;

struct Minibus
{
    public static explicit operator Minibus(Otobus bus)
    {
            //this anahtar sozcugunu static uyelerde kullanamayız!.
            //this.ayakta = bus.ayakta;
            //this.koltukSayisi = bus.koltukSayisi;
            //structlar new anahtar sozcugu ile olusmaya gerek duymazlar.
            Minibus mini;
            mini.ayakta = bus.ayakta;
            mini.koltukSayisi = bus.koltukSayisi;
            return mini;
    }
}
Yukarıdada görüldüğü gibi, kullanıcı tanımlı tiplere explicitly (cast operatörü ile ) tür dönüşümünü aritmetik ve mantıksal operatörlerle benzer şekilde öğrettik. Bu özel metotun erişim belirleyicisi public ve niteleyicisi statik olmak zorundadır.(Neden public ve static yukarda açıklanmıştır.)

Daha sonra hangi tür dönüşümünü öğreteceğimizi belirleyen implicit veya explicit anahtar sözcüklerinden birini seçiyoruz. Operatör anahtar sözcüğünden sonra atama operatörünün solunda kalacak olan tipi yani dönüştürülecek tipi belirtiyoruz. Bu tip ayrıca metotun dönüş tipi olarak belirlenip return anahtar sözcüğü ile döndürmemiz gereken tip haline geliyor.

Metotun parametre sayısı bir adet olmalıdır. Çünkü dönüşümü yapılacak tür birden fazla olamaz. Burdanda anlayabileceğimiz gibi, metotun aldığı parametre dönüşmesi gereken tipi işaret etmektedir.

methodbody

Program.cs dosyamıza tekrar bakalım ve değerleri ekrana yazdıralım;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("******Explicit ve Implicit overloading *******\n");
        //büyük olan tipimizi tanımlayalım ve degerlerini verelim.
        Otobus ikarus = new Otobus();
        ikarus.ayakta = 120;
        ikarus.koltukSayisi = 60+1;
        Console.WriteLine("otobus : {0}",ikarus);
        //küçük olan tipimizi tanımlayalım ve degerlerini verelim.
        Minibus deutz = new Minibus();
        deutz.ayakta = 15;
        deutz.koltukSayisi=25+1;
        Console.WriteLine("minibus : {0}\n",deutz);
        Console.WriteLine("******Explicit atamadan sonra*******\n");
        deutz= (Minibus)ikarus;
        Console.WriteLine("minibus : {0}", deutz);
    }       
}
out2
//Uygulamanın çalıştırıldıktan sonraki ekran çıktısı.


Kullanıcı tanımlı iki tip arasındaki bilinçli tür dönüşümlerini gördük. Acaba sistemde tanımlı tipler ile kullanıcı tanımlı tipler arasındada bu tarz explicit ve implicit atamalar yapılabilirmi? İsterseniz şimdi de bu soruya cevap arayalım...

public static explicit operator Minibus(int koltukAdet)
{
    Minibus mni;
    mni.koltukSayisi = koltukAdet;
    mni.ayakta = 0;
    return mni;
}
public static explicit operator int(Minibus mni)
{
    return mni.koltukSayisi;
}
Bilinçli (explicitly) atama yapılması istenecek birden fazla farklı tür için aşırı yüklenmiş metotları farklı parametreler alacak şekilde(metot imzası) aşırı yüklüyoruz.

Program.cs

Console.WriteLine("***int bir degerin kullanıcı tanımlı tipe explicit olarak atanması***");
int satinAlinanKoltuk=50;
Minibus magirus = (Minibus)satinAlinanKoltuk;
Console.WriteLine("magirus : {0}\n",magirus);
Console.WriteLine("***kullanıcı tanımlı bir degerin int değere explicit olarak atanması***");

Minibus schoolBus;
schoolBus.koltukSayisi = 19+1;
schoolBus.ayakta = 0;
int koltuklar = (int)schoolBus;
Console.WriteLine("koltuk sayısı : {0}", koltuklar);
out3

Uygulamamızın ekran çıktısındanda anlaşılacağı gibi sistemde tanımlı tipler ve kendi yazdığımız tipler arasında bilinçli tür dönüşümlerini kendi yazdığımız sınıfta operatör overloading yaparak sağlayabiliyoruz.

Implicitly (bilinçsiz) atamalar küçük bir türün güvenli bir şekilde büyük türe aktarıldığı atamalardır. Bizde kendi yazdığımız bu iki tip arasında bilinçiz atamaları gerçekleştirmek için Otobus struct ındaki gerekli güncellemeleri yapalım.

struct Otobus
{
    public int koltukSayisi;
    public int ayakta;
    public void YolcuDoldur()
    {
        Console.WriteLine("yolcular otobuse dolduruldu");
    }
    public override string ToString()
    {
        return string.Format("koltuk sayısı {0} ayakta yolcu sayısı {1}", koltukSayisi, ayakta);
    }
    public static implicit operator Otobus(Minibus mini)
    {
        Otobus oto; oto;
        oto.koltukSayisi = mini.koltukSayisi;
        oto.ayakta = mini.ayakta;
        return oto;
    }
}
Şimdide Program.cs’e dönüp bilinçiz atama işlemini gerçekleştirmeye çalışalım.

Console.WriteLine("***Implicitly Atamalar***");
Minibus vitobus;
vitobus.ayakta = 0;
vitobus.koltukSayisi = 15 + 1;
Otobus prenses = vitobus;
Console.WriteLine("otobus prenses : {0}",prenses);
//program.cs e eklenecek kod bloğu Küçük tür olarak tasarladığımız Minibus nesne örneği bilinçiz bir şekilde daha büyük bir tür olarak tasarladığımız Otobus nesne örneği üzerine alınıyor. Ekran çıktısına bakalım ve son durumu öğrenelim.

out4

Minibus yapısından oluşturduğumuz nesne örneği başarılı bir şekilde otobus nesne örneği üzerine alınmıştır.

Explicit atamalarda olduğu gibi imlplicit atamalardada framework’teki tipler ve kendi yazdığımız tipler arasındada atamalar gerçekleştirebilir.Tek yapmamız gerek uygun şekillerde operatör overload metotlarının overload metotlarını yazmaktır. Tıpkı diğer operatörde olduğu gibi explicit ve implicit operatörlerde CIL tarafında özel isimlerle ifade edilirler.

IL2

Operatör aşırı yükleme (overloading) işlemi işleri kolaylaştırmak için tercih edilir. Eğer yazdığınız sınıflar operatörlerle kullanıldığında işleri kolaylaştırmıyor aksine anlaşılmaz hale getiriyorsa operatör overload işlemlerinden kaçınmamız gerekir. Kendi yazdığımız sınıf(class) ve yapı(struct) larımızda operatör overload işlemlerini akıllıca kullanmalıyız.

Operatör aşırı yükleme konusunu incelemeye çalıştığımız bu makalemizin sonuna gelirken sizlere bir daha ki makalede buluşuncaya dek mutlu günler dilerim.

Umut Özkan
umut.ozkan@netron.com.tr
Makale:
Detayları ile Operatörleri Aşırı Yüklemek (Operator Overloading) C#, Visual C# ve .NET Umut Ozkan
  • Yazılan Yorumlar
  • Yorum Yaz
Bu konu hakkında yayınlanan yorum bulunmamaktadır.
"Yorum Yaz" tabını kullanarak sizde yorumlarınızı yazabilirsiniz.
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor