C# Operatörlerin Aşırı Yüklenmesi
C# programlama dilinde yer alan ve nesnelerin operatör işlemlerini yapmasına imkan veren operatörlerin aşırı yüklenmesi özelliği ile ilgili bilgiler yer alıyor.
Operatörlerin aşırı yüklenmesi nedir?
Birçok programlama dili temel veri türleri (int, double vb.) üzerinde işlem yapmak için çeşitli operatörleri kullanır.
int sayi1 = 5;
int sayi2 = 6;
int sonuc = sayi1 + sayi2;
Bu operatörler aritmetik (+, -, /, * ), karşılaştırma (<, >, ==, != vb.), mantıksal, bitsel operatörler gibi çeşitli gruplara ayrılır.
Temel veri türleri üzerinde işlem yapmak içi kullanılan operatörler programlama dili tarafından tanımlanmıştır.
Ancak biz bu operatörleri C# dilinde aşağıdaki gibi doğrudan nesneler üzerinde kullanamayız.
OrnekNesne n1 = new OrnekNesne();
OrnekNesne n2 = new OrnekNesne();
OrnekNesne n3 = n1 + n2;
Operatörlerin aşırı yüklenmesi özelliği ile bu işlemi tasarladığımız sınıflar içinde yapabiliriz.
C# programlama dili için birçok yerde C ve C++ dilinin devamı olarak ifade edilir.
Çünkü birçok özelliğini C ve C++ dilinden almıştır.
C++ dilinden aldığı özelliklerden birisi de operatörlerin aşırı yüklenmesidir.
Ancak operatörlerin aşırı yüklenmesi C++ dilindeki gibi geniş bir kullanımı yoktur (C++ dilinde akımlarda sıklıkla kullanılır).
C# programlama dilinde operatörlerin aşırı yüklenmesi için aşağıdaki metot tanımı kullanılır.
public static <dönüş-değeri> operator <operatör-işareti>(<parametre>) {}
NOT: Operatörlerin aldığı değere göre parametre sayısı değişebilir.
Operatörlerin aşırı yüklenmesi örneği
Operatörlerin aşırı yüklenmesi ile ilgili örnek aşağıda yer almaktadır.
class Sayi {
private int sayimiz;
public Sayi(int gelenSayi) {
this.sayimiz = gelenSayi;
}
public void Yazdir() {
Console.WriteLine(this.sayimiz);
}
public static Sayi operator +(Sayi a, Sayi b) {
return new Sayi(a.sayimiz + b.sayimiz);
}
}
Kullanımı aşağıdaki gibidir.
Sayi s1 = new Sayi(10);
Sayi s2 = new Sayi(10);
Sayi s3 = s1 + s2;
s3.Yazdir();
Tüm operatörleri tek tek anlatmak yazıyı uzatacağından operatörlerin aşırı yüklenmesi sırasında dikkat edilmesi gerekenleri yazacağım.
Örnekte sadece + veya toplama operatörü aşırı yüklenmiştir.
Aşırı yükleme sonucu döndürülecek nesnenin Sayi türünden olduğuna ve yeni bir nesne döndürdüğüne dikkat edin.
Burada toplama sonucunu int veya başka türden bir değişkene aktarmak istediğimizde dönüş değerini bu türden döndürebiliriz.
Her iki türden döndürmek istediğimizde karışıklık meydana geleceğinden sadece tek tür kabul edilmektedir.
class Sayi {
private int sayimiz;
public Sayi(int gelenSayi) {
this.sayimiz = gelenSayi;
}
public void Yazdir() {
Console.WriteLine(this.sayimiz);
}
public static int operator +(Sayi a, Sayi b) {
return a.sayimiz + b.sayimiz;
}
}
Kullanımı aşağıdaki gibidir.
Sayi s1 = new Sayi(10);
Sayi s2 = new Sayi(10);
int s3 = s1 + s2;
Console.WriteLine(s3);
Toplama operatörünün dönüş değerini int türünden döndürerek operatörlerin aşırı yüklenmesi özelliğini etkili bir şekilde kullanmış olmayız.
Daha sonra double, float veya string türüne çevirmek istediğimizde bu karışıklıktan dolayı olmayacaktır.
Peki toplama işlemini nasıl int türüne aktarabiliriz.
Bunu için C# içerisinde kullanılan bilinçli (explicit) veya bilinçsiz (implicit) tür dönüşümü operatörlerinin aşırı yüklenmesi gerekir.
Bilinçli tür dönüşümü aşağıdaki gibi tanımlanır.
public static explicit operator <dönüştürülecek-tür>(<tür>) {}
Bilinçsiz tür dönüşümü aşağıdaki gibi tanımlanır.
public static implicit operator <dönüştürülecek-tür>(<tür>) {}
NOT: Her iki tür aynı anda tanımlanamaz.
Bir tür bilinçsiz olarak dönüştürüldüğünde ve bilinçsiz tür dönüşümü tanımlanmadığında bilinçli tür dönüşümünü kullanacağından bilinçli (implicit) tür dönüşümünü tanımlamak faydalı olacaktır.
Tür dönüşümü sırasında veri kaybı olacaksa bu durumu açıkça belirtmek için bilinçsiz tür dönüşümü (explicit) kullanmak faydalı olacaktır.
class Sayi {
private int sayimiz;
public Sayi(int gelenSayi) {
this.sayimiz = gelenSayi;
}
public void Yazdir() {
Console.WriteLine(this.sayimiz);
}
public static Sayi operator +(Sayi a, Sayi b) {
return new Sayi(a.sayimiz + b.sayimiz);
}
public static implicit operator int(Sayi a) {
return a.sayimiz;
}
}
Tür dönüşümünü bildirerek artık nesnenin int türüne dönüşümünü sağlamış olduk.
Sayi s1 = new Sayi(10);
Sayi s2 = new Sayi(10);
int s3 = s1 + s2;
Console.WriteLine(s3);
Temel bir türün nesne türüne çevrilmesi için sadece dönüşüm parametresinin değiştirilmesi yeterli olacaktır.
Sayi s1 = 1453;
s1.Yazdir();
Yukarıdaki ifadenin geçerli olması için aşağıdaki metodun eklenmesi yeterli olacaktır.
public static implicit operator Sayi(int a) {
return new Sayi(a);
}
C# içerisinde yer alan String ifadelerinin karşılaştırılması sırasında operatörlerinin aşırı yüklenmesi kullanılır.
Benzer şekilde Decimal veri türü de operatörlerin aşırı yüklenmesi özelliğini kullanır.
Operatörlerin aşırı yüklenmesi ile ilgili en güzel örnek System.Numerics kütüphanesinde yer alan BigInteger sınıfıdır.
Bu sınıf int, double ve decimal sayılarından daha büyük sayılar üzerinde işlem yapmak için tasarlanmıştır ve operatörlerin aşırı yüklenmesi özelliğini kullanmaktadır.
C# 11 ile birlikte gelen static abstract, static virtual ve Generic math özellikleriyle birlikte operatörlerin aşırı yüklenmesinin daha anlaşılır olması için aşağıdaki arayüzler kullanılabilir.
Arayüz | Açıklama |
---|---|
IAdditionOperators | x + y |
IBitwiseOperators | x & y, x | y, x ^ y, ve ~x |
IComparisonOperators | x < y, x > y, x <= y, ve x >= y |
IDecrementOperators | –x ve x– |
IDivisionOperators | x / y |
IEqualityOperators | x == y ve x != y |
IIncrementOperators | ++x ve x++ |
IModulusOperators | x % y |
IMultiplyOperators | x * y |
IShiftOperators | x << y ve x >> y |
ISubtractionOperators | x – y |
IUnaryNegationOperators | -x |
IUnaryPlusOperators | +x |
IAdditiveIdentity | (x + T.AdditiveIdentity) == x |
IMinMaxValue | T.MinValue ve T.MaxValue |
IMultiplicativeIdentity | (x * T.MultiplicativeIdentity) == x |
Örnek kullanımı aşağıdaki gibidir.
using System.Numerics;
class Sayi : IAdditionOperators<Sayi, Sayi, Sayi> {
private int sayimiz;
public Sayi(int gelenSayi) {
this.sayimiz = gelenSayi;
}
public void Yazdir() {
Console.WriteLine(this.sayimiz);
}
public static Sayi operator +(Sayi a, Sayi b) {
return new Sayi(a.sayimiz + b.sayimiz);
}
public static implicit operator int(Sayi a) {
return a.sayimiz;
}
}
.NET ile geliştirme yaparken en çok kullanılan editör olan Visual Studio editörünün View menüsündeki Object Browser seçeneği ile bu sınıflarda yer alan metot imzalarının incelenmesi faydalı olacaktır.
C# Derslerine buradan ulaşabilirsiniz.
Hayırlı günler dilerim.