博客 / 詳情

返回

深入理解 C#.NET 運算符重載:語法、設計原則與最佳實踐

簡介

運算符重載是 C# 提供的一種特性,允許開發者為 自定義類型(類/結構體) 定義運算符的行為。
例如,可以讓 Vector 對象支持 + 運算,而不是僅限於基本類型(intdouble 等)。

💡 本質:運算符重載是一個 帶有 operator 關鍵字的靜態方法,通過自定義方法改變運算符的操作行為。

適用範圍與限制

特性 説明
可重載的類型 類(class)結構體(struct)
不可重載的類型 接口、枚舉、委託
方法修飾符 必須是 public static
至少一個自定義類型 運算符的參數中至少有一個必須是用户自定義類型
不能重載的運算符 .(成員訪問)、?:(條件運算符)、newisastypeofsizeof=, +=, -=(但可以間接重載)

支持重載的運算符

分類 運算符
一元運算符 + - ! ~ ++ -- true false
二元運算符 + - * / % & \`
比較運算符 == != < > <= >=(必須成對重載,如重載==則必須重載!=)
轉換運算符 implicit(隱式轉換) explicit(顯式轉換)

基本語法

public static 返回類型 operator 運算符(參數列表)
{
    // 自定義邏輯
}
  • operator 關鍵字定義運算符。
  • 參數中至少有一個是當前類/結構體。
  • 建議返回新的對象,保持不可變性。

常見示例

重載二元運算符(+)

創建一個二維向量類:

public struct Vector
{
    public double X { get; }
    public double Y { get; }

    public Vector(double x, double y) => (X, Y) = (x, y);

    public static Vector operator +(Vector a, Vector b)
        => new Vector(a.X + b.X, a.Y + b.Y);

    public override string ToString() => $"({X}, {Y})";
}

// 使用
var v1 = new Vector(1, 2);
var v2 = new Vector(3, 4);
Console.WriteLine(v1 + v2); // 輸出: (4, 6)

重載一元運算符(-)

public static Vector operator -(Vector v)
    => new Vector(-v.X, -v.Y);

var v = new Vector(5, -3);
Console.WriteLine(-v); // 輸出: (-5, 3)

重載比較運算符(==, !=)

比較向量是否相等:

public static bool operator ==(Vector a, Vector b)
    => a.X == b.X && a.Y == b.Y;

public static bool operator !=(Vector a, Vector b)
    => !(a == b);

// 建議同時重寫 Equals 和 GetHashCode
public override bool Equals(object? obj)
    => obj is Vector v && this == v;
public override int GetHashCode()
    => HashCode.Combine(X, Y);
  • 重載 == 時 必須 同時重載 !=
  • EqualsGetHashCode 也要同步實現,保證一致性。

重載遞增/遞減運算符(++/--)

public static Vector operator ++(Vector v)
    => new Vector(v.X + 1, v.Y + 1);

public static Vector operator --(Vector v)
    => new Vector(v.X - 1, v.Y - 1);

轉換運算符(implicit/explicit)

Vectordouble 之間轉換:

public static implicit operator double(Vector v)
    => Math.Sqrt(v.X * v.X + v.Y * v.Y); // 隱式轉換為長度

public static explicit operator Vector(double d)
    => new Vector(d, d); // 需要強制轉換

使用:

Vector v = new Vector(3, 4);
double len = v; // 隱式轉換
Vector v2 = (Vector)5.0; // 顯式轉換

邏輯運算符(true/false)

用於自定義布爾邏輯:

public static bool operator true(Vector v) => v.X != 0 || v.Y != 0;
public static bool operator false(Vector v) => v.X == 0 && v.Y == 0;

Vector v = new Vector(0, 0);
if (v) // 自動調用 operator true
    Console.WriteLine("非零向量");
else
    Console.WriteLine("零向量");

運算符與方法的關係

運算符重載只是語法糖,編譯器會將運算符轉換為靜態方法調用:

var c = a + b;
// 等價於
var c = Vector.op_Addition(a, b);

常用方法映射:

運算符 生成的方法名
+ op_Addition
- op_Subtraction
* op_Multiply
/ op_Division
== op_Equality
!= op_Inequality

綜合示例:複數類

public struct Complex
{
    public double Real { get; }
    public double Imag { get; }

    public Complex(double real, double imag)
        => (Real, Imag) = (real, imag);

    public static Complex operator +(Complex a, Complex b)
        => new Complex(a.Real + b.Real, a.Imag + b.Imag);

    public static Complex operator -(Complex a, Complex b)
        => new Complex(a.Real - b.Real, a.Imag - b.Imag);

    public static Complex operator *(Complex a, Complex b)
        => new Complex(a.Real * b.Real - a.Imag * b.Imag,
                       a.Real * b.Imag + a.Imag * b.Real);

    public static bool operator ==(Complex a, Complex b)
        => a.Real == b.Real && a.Imag == b.Imag;

    public static bool operator !=(Complex a, Complex b)
        => !(a == b);

    public override string ToString() => $"{Real} + {Imag}i";
}

總結

特性 説明
適用場景 數學計算類(向量、矩陣、複數)、日期時間、座標類
關鍵規則 public static、至少一個參數為自定義類型
搭配使用 EqualsGetHashCodeIComparable
設計建議 遵循語義一致性、返回新對象、與方法重載保持協調
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.