运算符重载(Operator Overloading)

在 C# 中,运算符重载(Operator Overloading) 是一种允许你为自定义的类或结构体重新定义运算符行为的特性。通过运算符重载,你可以让自定义类型像内置类型(如 int、string)一样,直接使用 +、-、== 等运算符进行操作,使代码更简洁、直观。

核心要点
目的
让自定义类型支持运算符操作,提升代码可读性。例如,用 a + b 代替 a.Add(b)。

实现方式
通过定义 public static 方法,并使用 operator 关键字声明要重载的运算符:

1
2
复制
public static 返回类型 operator 运算符(参数) { ... }

可重载的运算符

算术运算符:+, -, *, /, %

比较运算符:==, !=, <, >, <=, >=

逻辑运算符:!,&, |, ^

位运算符: < <, >>

类型转换运算符:implicit(隐式转换)和 explicit(显式转换)

其他:true, false, ++, –

不可重载的运算符:
& &, ||, =, new, is, as, ??, =>, . 等。


简单示例
假设有一个表示二维向量的类 Vector,重载 + 运算符实现向量相加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
复制
public class Vector
{
public double X { get; set; }
public double Y { get; set; }

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

// 重载 + 运算符
public static Vector operator +(Vector v1, Vector v2)
{
return new Vector(v1.X + v2.X, v1.Y + v2.Y);
}

// 重写 ToString 方便输出
public override string ToString() => $"({X}, {Y})";
}

// 使用示例
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector sum = v1 + v2; // 直接使用 + 运算符
Console.WriteLine(sum); // 输出 "(4, 6)"

关键规则
必须为静态方法
运算符重载的方法必须是 public static。

参数和返回类型

运算符的操作数必须包含当前类型(例如 Vector + Vector)。

返回类型可以是任意类型,但通常与当前类型一致。

成对重载

若重载 ==,必须同时重载 !=。

若重载 <,通常需要重载 >、 <=、>=。

重写 Equals 和 GetHashCode
如果重载了比较运算符(如 ==),必须同时重写 Equals() 和 GetHashCode(),确保逻辑一致。

典型应用场景
数学对象
复数、矩阵、多项式等需要算术运算的类型。

1
2
3
4
复制
Complex c1 = new Complex(1, 2);
Complex c2 = new Complex(3, 4);
Complex sum = c1 + c2; // 直接相加

物理量
距离、速度、温度等需要运算符操作的物理量。

1
2
3
4
复制
Distance d1 = new Distance(10, Unit.Meter);
Distance d2 = new Distance(5, Unit.Meter);
Distance total = d1 + d2; // 自动单位转换并相加

自定义逻辑
例如重载 + 合并集合,或重载 == 比较对象的业务逻辑等价性。

注意事项
避免滥用
运算符的行为必须符合直觉。例如,+ 不应被重载为减法操作。

性能优化
避免在运算符重载中执行复杂操作(如数据库查询)。

隐式/显式转换
使用 implicit 或 explicit 定义类型转换时需谨慎,确保不会导致歧义。

总结

运算符重载让自定义类型可以像内置类型一样使用运算符,使代码更简洁、直观。但需遵循语义合理性(如 + 表示加法)和一致性原则(如成对重载 == 和 !=)。正确使用时,能大幅提升代码可读性;滥用则会导致代码难以维护。