共用方式為


運算子多載 - 預定義的一元運算子、算術運算子、相等運算子和比較運算子

使用者定義的類型可以多載預先定義的 C# 運算子。 也就是說,如果其中一個操作數或兩個操作數都屬於該類型,類型可以提供操作的自定義實作。 [可多載運算符] 區段會顯示哪些 C# 運算符可以多載。

operator使用 關鍵詞來宣告運算符。 運算符宣告必須滿足下列規則:

  • 它包含 public 修飾詞。
  • 一元運算子有一個輸入參數。 二元運算子有兩個輸入參數。 在每個案例中,至少有一個參數必須有類型T,其中 T?T 是包含運算符宣告的類型。
  • 它包含 static 修飾詞,但複合指派運算元除外,例如 +=
  • 遞增 (++) 和遞減 (--) 運算子可以實作為靜態或實例方法。

下列範例會定義簡化的結構來表示理性的數位。 結構會多載一些 算術運算子

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

您可以透過定義從到的隱含轉換來擴充上述範例。 然後,多載運算符將支援這兩類型的參數。 也就是說,可以將整數加入到分數中,並取得分數作為結果。

您也可以使用 operator 關鍵字來定義自訂類型轉換。 如需詳細資訊,請參閱使用者定義轉換運算子

可重載運算子

下表顯示可多載的運算子:

運營商 註釋
+x-x!x~x++--truefalse truefalse運算子必須一起重載。
x + y、、x - yx * yx / y、、x % y
x & y、 、 x | yx ^ y
x << yx >> yx >>> y
x == yx != yx < yx > yx <= yx >= y 必須以配對方式多載,如下所示:==!=<><=>=
+=-=*=/=%=&=\|=^=<<=>>=>>>= 複合指派運算子可以在 C# 14 和更新版本中多載。

複合指派多載運算符必須遵循下列規則:

  • 它必須包含 public 修飾詞。
  • 它不能包含 static 修飾詞。
  • 傳回型別必須是 void
  • 宣告必須包含一個參數,代表複合指派的右邊。

從 C# 14 開始,遞增 (++) 和遞減 (--) 運算符可以多載為實例成員。 實例運算子可以藉由避免建立新的實例來改善效能。 實體運算子必須遵循下列規則:

  • 它必須包含 public 修飾詞。
  • 它不能包含 static 修飾詞。
  • 傳回型別必須是 void
  • 即使這些參數具有預設值,它也無法宣告任何參數。

不可多載運算子

下表顯示無法多載的運算子:

運營商 替代選擇
x && yx || y 重載truefalse運算子,以及&|運算子。 如需詳細資訊,請參閱 使用者定義的條件式邏輯運算符
a[i]a?[i] 定義 索引器
(T)x 定義轉換表達式所執行的自定義類型轉換。 如需詳細資訊,請參閱使用者定義轉換運算子
^xx = yx.yx?.yc ? t : fx ?? y、、、 ??= y
x..yx->y=>f(x)asawaitcheckeduncheckeddefaultdelegateisnameofnew
sizeofstackallocswitchtypeofwith
沒有。

在 C# 14 之前,無法多載複合運算子。 重載相應的二元運算子會隱含重載相應的複合賦值運算子。

運算子多載解析

這很重要

本節適用於 C# 14 和更新版本。 在 C# 14 之前,不允許使用者定義的複合指派運算符和實例遞增和遞減運算符。

如果 x 在複合指派表達式中分類為變數,例如 x «op»= y,則實例運算符優先於任何靜態運算符 «op»。 如果未針對«op»=的類型宣告多載x運算符,或x未被分類為變數,則會使用靜態運算符。

對於後置運算符 ++,如果未 x 分類為變數 或使用 表達式 x++ ,則會忽略 實例 operator++ 。 否則,會優先選擇實例operator ++。 例如,

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

此規則的原因是應該在遞增之前指派y的值給x 編譯器無法判斷在參考型別中使用者定義的實作。

對於前置詞運算符 ++,如果 x 分類為 中的 ++x變數,則實例運算符優先於靜態一元運算符。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

另請參閱