Bagikan melalui


Kelebihan beban operator - operator unary, aritmetic, equality, dan perbandingan yang telah ditentukan sebelumnya

Jenis yang ditentukan pengguna dapat membebani operator C# yang telah ditentukan sebelumnya. Artinya, jenis dapat memberikan implementasi kustom operasi jika salah satu atau kedua operan berjenis tersebut. Bagian Operator yang Dapat Kelebihan Beban menunjukkan operator C# mana yang dapat kelebihan beban.

operator Gunakan kata kunci untuk mendeklarasikan operator. Deklarasi operator harus memenuhi aturan berikut:

  • Ini termasuk pengubah public .
  • Operator unary memiliki satu input parameter. Operator biner memiliki dua parameter input. Dalam setiap kasus, setidaknya satu parameter harus memiliki jenis T atau T? di mana T adalah jenis yang berisi deklarasi operator.
  • Ini termasuk pengubah static , kecuali untuk operator penugasan campuran, seperti +=.
  • Operator kenaikan (++) dan penurunan (--) dapat diimplementasikan sebagai metode statis atau instans.

Contoh berikut menentukan struktur yang disederhanakan untuk mewakili angka rasional. Struktur membebani beberapa operator aritmatika:

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
    }
}

Anda dapat memperluas contoh sebelumnya dengan menentukan konversi implisit dari int ke Fraction. Kemudian, operator yang kelebihan beban akan mendukung argumen dari dua jenis tersebut. Artinya, akan menjadi mungkin untuk menambahkan bilangan bulat ke pecahan dan mendapatkan pecahan sebagai hasilnya.

Anda juga menggunakan operator kata kunci untuk menentukan konversi jenis kustom. Untuk informasi selengkapnya, lihat Operator konversi yang ditentukan pengguna.

Operator yang dapat di-overload

Tabel berikut ini memperlihatkan operator yang bisa kelebihan beban:

Para Operator Catatan
+x, , -x!x, ~x, ++, --, , true,false Operator true dan false harus kelebihan beban bersama-sama.
x + y, , x - yx * y, x / y, , x % y,
x & y, x | y, x ^ y,
x << y, , x >> yx >>> y
x == y, , x != yx < y, x > y, , x <= y,x >= y Harus kelebihan beban berpasangan sebagai berikut: == dan !=, < dan >, <= dan >=.
+=, , -=*=, /=, %=, &=, \|=, ^=, <<=, , , >>=>>>= Operator penugasan gabungan dapat kelebihan beban di C# 14 dan yang lebih baru.

Operator yang kelebihan beban penugasan gabungan harus mengikuti aturan berikut:

  • Ini harus mencakup pengubah public .
  • Ini tidak dapat menyertakan pengubah static .
  • Tipe pengembalian harus void.
  • Deklarasi harus mencakup satu parameter, yang mewakili sisi kanan pengalokasian gabungan.

Dimulai dengan C# 14, operator kenaikan (++) dan penurunan (--) dapat kelebihan beban sebagai anggota instans. Operator instans dapat meningkatkan performa dengan menghindari pembuatan instans baru. Operator instans harus mengikuti aturan ini:

  • Ini harus mencakup pengubah public .
  • Ini tidak dapat menyertakan pengubah static .
  • Tipe pengembalian harus void.
  • Ini tidak dapat mendeklarasikan parameter apa pun, bahkan jika parameter tersebut memiliki nilai default.

Operator yang tidak dapat di-overload

Tabel berikut ini memperlihatkan operator yang tidak dapat kelebihan beban:

Para Operator Alternatif
x && y, x || y Overload kedua operator true dan false, serta operator & atau |. Untuk informasi selengkapnya, lihat Operator logis kondisional yang ditentukan pengguna.
a[i], a?[i] Tentukan pengindeks.
(T)x Definisikan konversi tipe kustom yang dilakukan oleh ekspresi cast. Untuk informasi selengkapnya, lihat Operator konversi yang ditentukan pengguna.
^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, , stackallocswitch, , typeof,with
Tidak ada.

Sebelum C# 14, operator senyawa tidak dapat kelebihan beban. Kelebihan beban operator biner yang sesuai secara implisit membebani operator penetapan majemuk yang sesuai.

Resolusi kelebihan beban operator

Penting

Bagian ini berlaku untuk C# 14 dan yang lebih baru. Sebelum C# 14, operator penugasan gabungan yang ditentukan pengguna, serta operator peningkatan dan penurunan instans, tidak diizinkan.

Jika x diklasifikasikan sebagai variabel dalam ekspresi penetapan gabungan seperti x «op»= y, operator instans lebih disukai daripada operator statis apa pun untuk «op». Jika operator «op»= yang di-overload tidak dinyatakan untuk tipe x atau x tidak diklasifikasikan sebagai variabel, operator statis akan digunakan.

Untuk operator ++postfix , jika x tidak diklasifikasikan sebagai variabel atau ekspresi x++ digunakan, instans operator++ diabaikan. Jika sebaliknya, preferensi diberikan kepada instans operator ++. Contohnya,

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

Alasan untuk aturan ini adalah bahwa y harus ditetapkan ke nilai xsebelum dinaikkan. Pengkompilasi tidak dapat menentukan implementasi yang ditentukan pengguna dalam tipe referensi.

Untuk operator awalan ++, jika x diklasifikasikan sebagai variabel dalam ++x, operator instans lebih disukai daripada operator unary statis.

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat bagian berikut dari spesifikasi bahasa C#:

Lihat juga