使用者定義的類型可以多載預先定義的 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 、++ 、-- 、true 、false |
true 和false 運算子必須一起重載。 |
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 |
必須以配對方式多載,如下所示:== 和 != 、< 和 > 、<= 和 >= 。 |
+= 、-= 、*= 、/= 、%= 、&= 、\|= 、^= 、<<= 、>>= 、>>>= |
複合指派運算子可以在 C# 14 和更新版本中多載。 |
複合指派多載運算符必須遵循下列規則:
- 它必須包含
public
修飾詞。 - 它不能包含
static
修飾詞。 - 傳回型別必須是
void
。 - 宣告必須包含一個參數,代表複合指派的右邊。
從 C# 14 開始,遞增 (++
) 和遞減 (--
) 運算符可以多載為實例成員。 實例運算子可以藉由避免建立新的實例來改善效能。 實體運算子必須遵循下列規則:
- 它必須包含
public
修飾詞。 - 它不能包含
static
修飾詞。 - 傳回型別必須是
void
。 - 即使這些參數具有預設值,它也無法宣告任何參數。
不可多載運算子
下表顯示無法多載的運算子:
運營商 | 替代選擇 |
---|---|
x && y 、x || y |
重載true 和false 運算子,以及& 或| 運算子。 如需詳細資訊,請參閱 使用者定義的條件式邏輯運算符。 |
a[i] 、a?[i] |
定義 索引器。 |
(T)x |
定義轉換表達式所執行的自定義類型轉換。 如需詳細資訊,請參閱使用者定義轉換運算子。 |
^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 |
沒有。 |
在 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# 語言規格的下列幾節: