Aracılığıyla paylaş


İşleç aşırı yüklemesi - önceden tanımlanmış tekli, aritmetik, eşitlik ve karşılaştırma işleçleri

Kullanıcı tanımlı bir tür, önceden tanımlanmış bir C# işlecini aşırı yükleyebilir. Başka bir ifadeyle, işlenenlerden birinin veya her ikisinin de bu türde olması durumunda, bir tür bir işlemin özel uygulamasını sağlayabilir. Aşırı yüklenebilir işleçler bölümünde hangi C# işleçlerinin aşırı yüklenebileceği gösterilir.

operator bir işleci bildirmek için anahtar sözcüğünü kullanın. Bir işleç bildirimi aşağıdaki kuralları karşılamalıdır:

  • Bir değiştirici içerir public .
  • Birli işleç bir giriş parametresine sahiptir. İkili işleç iki giriş parametresine sahiptir. Her durumda, en az bir parametrenin türü T olmalıdır veya T? burada T işleç bildirimini içeren türdür.
  • static değiştiriciyi, += gibi bileşik atama işleçleri dışında içerir.
  • Artım (++) ve azaltma (--) işleçleri statik veya örnek yöntemleri olarak uygulanabilir.

Aşağıdaki örnek, rasyonel bir sayıyı temsil eden basitleştirilmiş bir yapı tanımlar. Yapı, bazı aritmetik işleçleri aşırı yükler:

public struct Fraction
{
    private int numerator;
    private int denominator;

    public Fraction(int numerator, int denominator)
    {
        if (denominator == 0)
        {
            throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
        }
        this.numerator = numerator;
        this.denominator = denominator;
    }

    public static Fraction operator +(Fraction operand) => operand;
    public static Fraction operator -(Fraction operand) => new Fraction(-operand.numerator, operand.denominator);

    public static Fraction operator +(Fraction left, Fraction right)
        => new Fraction(left.numerator * right.denominator + right.numerator * left.denominator, left.denominator * right.denominator);

    public static Fraction operator -(Fraction left, Fraction right)
        => left + (-right);

    public static Fraction operator *(Fraction left, Fraction right)
        => new Fraction(left.numerator * right.numerator, left.denominator * right.denominator);

    public static Fraction operator /(Fraction left, Fraction right)
    {
        if (right.numerator == 0)
        {
            throw new DivideByZeroException();
        }
        return new Fraction(left.numerator * right.denominator, left.denominator * right.numerator);
    }

    // Define increment and decrement to add 1/den, rather than 1/1.
    public static Fraction operator ++(Fraction operand)
        => new Fraction(operand.numerator++, operand.denominator);

    public static Fraction operator --(Fraction operand) =>
        new Fraction(operand.numerator--, operand.denominator);

    public override string ToString() => $"{numerator} / {denominator}";

    // New operators allowed in C# 14:
    public void operator +=(Fraction operand) =>
        (numerator, denominator ) =
        (
            numerator * operand.denominator + operand.numerator * denominator,
            denominator * operand.denominator
        );

    public void operator -=(Fraction operand) =>
        (numerator, denominator) =
        (
            numerator * operand.denominator - operand.numerator * denominator,
            denominator * operand.denominator
        );

    public void operator *=(Fraction operand) =>
        (numerator, denominator) =
        (
            numerator * operand.numerator,
            denominator * operand.denominator
        );

    public void operator /=(Fraction operand)
    {
        if (operand.numerator == 0)
        {
            throw new DivideByZeroException();
        }
        (numerator, denominator) =
        (
            numerator * operand.denominator,
            denominator * operand.numerator
        );
    }

    public void operator ++() => numerator++;

    public void operator --() => numerator--;
}

public static class OperatorOverloading
{
    public static void Main()
    {
        var a = new Fraction(5, 4);
        var b = new Fraction(1, 2);
        Console.WriteLine(-a);   // output: -5 / 4
        Console.WriteLine(a + b);  // output: 14 / 8
        Console.WriteLine(a - b);  // output: 6 / 8
        Console.WriteLine(a * b);  // output: 5 / 8
        Console.WriteLine(a / b);  // output: 10 / 4
    }
}

Önceki örneği, 'den int'ye Fraction genişletebilirsiniz. Ardından, aşırı yüklenmiş işleçler bu iki türden gelen bağımsız değişkenleri destekler. Yani, bir tamsayıyı bir kesirle toplamak ve sonuçta bir kesir elde etmek mümkün hale gelir.

Özel tür dönüştürmesi tanımlamak için operator anahtar sözcüğünü de kullanırsınız. Daha fazla bilgi için bkz . Kullanıcı tanımlı dönüştürme işleçleri.

Aşırı yüklenebilir işleçler

Aşağıdaki tabloda aşırı yüklenebilen işleçler gösterilmektedir:

Operatörler Notlar
+x, -x, !x, , ~x, ++, --, true, false true ve false işleçleri birlikte aşırı yüklenmelidir.
x + y, x - y, x * y, , x / y, x % y,
x & y, x | y, x ^ y,
x << y, x >> y, x >>> y
x == y, x != y, x < y, , x > y, x <= y, x >= y aşağıdaki gibi çiftler halinde aşırı yüklenmelidir: == ve !=, < ve ><= ve >=.
+=, -=, , *=, /=, %=, &=, , \|=^=, <<=, >>=,>>>= Bileşik atama işleçleri C# 14 ve sonraki sürümlerde aşırı yüklenebilir.

Aşırı yüklenmiş bileşik atama operatörü aşağıdaki kurallara uymalıdır:

  • Değiştiriciyi public içermelidir.
  • Değiştiriciyi static içeremez.
  • Dönüş türü void olmalıdır.
  • Bildirim, bileşik atamanın sağ tarafını temsil eden bir parametre içermelidir.

C# 14'le başlayarak, artım (++) ve azaltma (--) işleçleri örnek üyesi olarak aşırı yüklenebilir. Örnek işleçleri, yeni bir örneğin oluşturulmasını önleyerek performansı geliştirebilir. Örnek işleci şu kurallara uymalıdır:

  • Değiştiriciyi public içermelidir.
  • Değiştiriciyi static içeremez.
  • Dönüş türü void olmalıdır.
  • Bu parametreler varsayılan değere sahip olsa bile herhangi bir parametre bildiremez.

Aşırı yüklenemez işleçler

Aşağıdaki tabloda aşırı yüklenemeyen işleçler gösterilmektedir.

Operatörler Alternatifler
x && y, x || y Hem true ve false işleçlerini, hem de & veya | işleçlerini aşırı yükleyin. Daha fazla bilgi için bkz. Kullanıcı tanımlı koşullu mantıksal işleçler.
a[i], a?[i] Dizin oluşturucu tanımlayın.
(T)x Bir cast ifadesi tarafından gerçekleştirilen özel tür dönüşümlerini tanımlayın. Daha fazla bilgi için bkz . Kullanıcı tanımlı dönüştürme işleçleri.
^x, x = y, x.y, , x?.y, c ? t : f, x ?? y, ??= y,
x..y, x->y, =>, f(x), as, await, checked, unchecked, default, delegate, is, nameof, new,
sizeof, stackalloc, switch, typeof, , with
Yok.

C# 14'e geçmeden önce bileşik işleçler aşırı yüklenemez. karşılık gelen ikili işlecin aşırı yüklenmesi, ilgili bileşik atama işlecini örtük olarak aşırı yükler.

İşleç aşırı yükleme çözümlemesi

Önemli

Bu bölüm C# 14 ve üzeri için geçerlidir. C# 14'e geçmeden önce kullanıcı tanımlı bileşik atama işleçleri ile örnek artırma ve azaltma işleçlerine izin verilmez.

x gibi bir bileşik atama ifadesinde değişken olarak sınıflandırılırsa, x «op»= y için herhangi bir statik işleç yerine örnek işleçleri tercih edilir. Eğer aşırı yüklenmiş «op»= işleci x türü için bildirilmediyse veya x bir değişken olarak sınıflandırılmamışsa, statik işleçler kullanılır.

sonek işleci ++ için, x değişken olarak sınıflandırılmazsa veya ifade kullanılırsa, örnek x++ yoksayılır. Aksi takdirde, operator ++ örneği tercih edilir. Örneğin

x++; // Instance operator++ preferred.
y = x++; // instance operator++ isn't considered.

Bu kuralın nedeni, yx atanması gerektiğidir. Derleyici, başvuru türündeki kullanıcı tanımlı bir uygulama için bunu belirleyemez.

Ön eki işleci ++ için, x++x içinde bir değişken olarak sınıflandırılırsa, örnek işleç statik bir unary operatör yerine tercih edilir.

C# dil belirtimi

Daha fazla bilgi için C# dil belirtimininaşağıdaki bölümlerine bakın:

Ayrıca bakınız