在 C# 中,运算符重载允许你为自定义类型(如结构体或类)定义 +、-、*、/、== 等运算符的行为,让它们像内置类型一样自然参与算术或比较运算。
哪些运算符可以重载
不是所有运算符都能重载。C# 支持重载的包括:
一元运算符:+、-、!、~、++、--、true、false 二元运算符:+、-、*、/、%、&、|、^、、>>、==、!=、、>、、>= 必须成对重载的比较运算符:== 和 !=,或 和 > 等(否则编译报错)基本语法和规则
运算符重载必须用 public static 修饰,且至少一个参数是当前类型。不能改变运算符的优先级、结合性或操作数个数。
例如,为表示二维坐标的 Point 结构重载加法:
public struct Point
{
public int X { get; }
public int Y { get; }
<pre class="brush:php;toolbar:false;">public Point(int x, int y) => (X, Y) = (x, y);
public static Point operator +(Point a, Point b) =>
new Point(a.X + b.X, a.Y + b.Y);}
之后就能直接写:
var p3 = p1 + p2;
重载相等运算符(== 和 !=)的注意事项
如果重载了 == 和 !=,强烈建议同时重写 Equals(object)、GetHashCode(),并实现 IEquatable
典型写法:
先判断是否为 null(引用类型)或使用 ReferenceEquals(避免递归) 用成员逐项比较,避免装箱(值类型慎用 object.Equals) GetHashCode 必须与 Equals 逻辑一致:相等的对象必须返回相同哈希码常见陷阱与建议
运算符重载不是语法糖,而是语义契约——它应该符合直觉。比如 + 应该是无副作用、可交换的;== 应该是自反、对称、传递的。
避免重载让代码难以理解,比如用 + 触发网络请求 结构体尽量用 readonly struct 配合运算符重载,保证不可变性 不要重载 && 或 ||(短路逻辑),C# 不支持;可用 & 和 | 替代(但语义不同) 用户定义的转换运算符(implicit/explicit)可配合运算符提升表达力,但要谨慎防止隐式转换引发歧义基本上就这些。合理使用运算符重载能让自定义类型更自然、更安全地融入 C# 的表达习惯。
