1. 什么是运算符重载?
运算符重载 是 C# 提供的一种机制,允许我们为自定义类型(class、struct)定义运算符的行为。
简单来说:
让对象也可以像基本数据类型一样使用
+、-、==、>等运算符。
例如:
普通写法:
cs
Point p3 = p1.Add(p2);
使用运算符重载后:
cs
Point p3 = p1 + p2;
代码更加直观。
2. 为什么需要运算符重载?
假设我们定义一个二维坐标类:
cs
class Point
{
public int X;
public int Y;
}
现在有两个点:
Point p1 = new Point(10,20);
Point p2 = new Point(5,8);
我们希望:
p1 + p2
得到:
(15,28)
但是 C# 不知道两个对象如何相加。
所以需要告诉编译器:
当两个 Point 使用 + 时,应该怎么计算。
这就是运算符重载。
3. 运算符重载的基本语法
格式:
cs
public static 返回类型 operator 运算符(参数)
{
// 运算逻辑
}
例如:
cs
public static Point operator +(Point p1, Point p2)
{
return new Point(
p1.X + p2.X,
p1.Y + p2.Y
);
}
关键点:
| 关键字 | 作用 |
|---|---|
| public | 必须公开 |
| static | 必须静态 |
| operator | 表示重载运算符 |
| + | 要重载的运算符 |
4. 示例:重载 + 运算符
完整代码:
cs
using System;
class Point
{
public int X;
public int Y;
public Point(int x,int y)
{
X=x;
Y=y;
}
public static Point operator +(Point p1, Point p2)
{
return new Point(
p1.X+p2.X,
p1.Y+p2.Y
);
}
public void Show()
{
Console.WriteLine($"({X},{Y})");
}
}
class Program
{
static void Main()
{
Point p1=new Point(10,20);
Point p2=new Point(5,8);
Point p3=p1+p2;
p3.Show();
}
}
输出:
(15,28)
5. 运算符重载的规则
规则1:必须是 static
错误:
cs
public Point operator +(Point p)
{
}
正确:
cs
public static Point operator +(Point p1,Point p2)
{
}
原因:
运算符属于类型,而不是对象。
规则2:至少一个参数必须是当前类型
例如:
cs
class Money
{
}
允许:
cs
Money + Money
允许:
Money + int
不允许:
int + int
因为 C# 已经定义好了。
规则3:不能修改原对象
推荐:
cs
public static Money operator +(Money a,Money b)
{
return new Money(a.Value+b.Value);
}
不要:
cs
a.Value += b.Value;
return a;
原因:
容易产生隐藏副作用。
6. 可以重载哪些运算符?
6.1 算术运算符
| 运算符 | 说明 |
|---|---|
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 取模 |
例如:
cs
public static Vector operator -(Vector a,Vector b)
{
return new Vector(
a.X-b.X,
a.Y-b.Y
);
}
6.2 比较运算符
可以重载:
==
!=
>
<
>=
<=
例如:
cs
class Student
{
public int Score;
public static bool operator >
(Student a,Student b)
{
return a.Score>b.Score;
}
public static bool operator <
(Student a,Student b)
{
return a.Score<b.Score;
}
}
使用:
cs
Student s1=new Student();
Student s2=new Student();
if(s1>s2)
{
Console.WriteLine("s1成绩更高");
}
7. == 和 != 重载
这是最容易出问题的地方。
例如:
cs
class Person
{
public string Name;
}
比较:
cs
Person p1=new Person();
Person p2=new Person();
Console.WriteLine(p1==p2);
默认比较:
地址
不是内容。
重载:
cs
public static bool operator ==
(Person a,Person b)
{
return a.Name==b.Name;
}
public static bool operator !=
(Person a,Person b)
{
return !(a==b);
}
现在:
p1==p2
比较:
姓名是否相同
8. 一元运算符重载
一元运算符只有一个参数:
例如:
++
--
-
!
~
例:
重载负号 -
cs
class Number
{
public int Value;
public static Number operator -(Number n)
{
return new Number
{
Value=-n.Value
};
}
}
使用:
cs
Number n=new Number();
Number result=-n;
9. ++ 和 -- 运算符
例如:
cs
class Counter
{
public int Value;
public static Counter operator ++(Counter c)
{
c.Value++;
return c;
}
}
使用:
Counter c=new Counter();
c++;
10. 类型转换运算符重载
C# 支持:
隐式转换 implicit
自动转换:
int i = money;
语法:
cs
public static implicit operator int(Money m)
{
return m.Value;
}
显式转换 explicit
需要强制:
int i=(int)money;
定义:
cs
public static explicit operator int(Money m)
{
return m.Value;
}
11. 实战案例:人民币类
需求:
cs
Money a=100;
Money b=200;
Money c=a+b;
Console.WriteLine(c);
代码:
cs
class Money
{
public decimal Amount;
public Money(decimal amount)
{
Amount=amount;
}
public static Money operator +
(Money a,Money b)
{
return new Money(
a.Amount+b.Amount
);
}
public override string ToString()
{
return Amount+"元";
}
}
使用:
cs
Money m1=new Money(100);
Money m2=new Money(200);
Money m3=m1+m2;
Console.WriteLine(m3);
输出:
300元
12. 运算符重载与方法的区别
| 比较 | 方法 | 运算符重载 |
|---|---|---|
| 调用方式 | Add() | + |
| 可读性 | 一般 | 高 |
| 适合数学对象 | 一般 | 非常适合 |
| 灵活性 | 高 | 有限 |
例如:
数学类型:
Vector
Matrix
Complex
Money
Time
Date
适合使用。
13. 不能重载的运算符
以下不能重载:
| 运算符 |
|---|
| . |
| ?: |
| ?? |
| => |
| new |
| typeof |
| sizeof |
| is |
| as |
原因:
这些属于语言结构,不是普通运算。
14. 最佳实践
推荐使用场景
✅ 数学对象
Vector v1+v2
✅ 金融对象
Money+Money
✅ 日期时间
DateTime+TimeSpan
✅ 单位类型
Length+Length
不推荐
不要这样:
User user1 + User user2
因为:
用户相加没有自然意义
会降低代码可读性。
15. 面试常问问题
Q1:运算符重载是什么?
答:
运算符重载允许自定义类型重新定义已有运算符的行为,使对象能够像基础类型一样进行运算。
Q2:为什么运算符重载必须 static?
答:
因为运算符属于类型级别的方法,不属于某一个实例。
Q3:== 重载需要注意什么?
答:
需要同时重载:
==
!=
并且通常还需要重写:
Equals()
GetHashCode()
Q4:struct 和 class 都可以重载吗?
答:
可以。
例如:
cs
struct Vector
{
public static Vector operator+
}
总结
C# 运算符重载核心:
让对象支持运算
↓
定义 operator 方法
↓
必须 static
↓
返回新对象
↓
提高代码可读性
学习顺序建议:
类(Class)
↓
继承
↓
多态
↓
接口
↓
运算符重载
↓
泛型
↓
委托/Lambda
↓
LINQ
运算符重载是 C# 面向对象编程中非常重要的一部分,尤其在开发 游戏、图形、金融系统、数学计算库 时使用非常广泛。