C# 运算符重载详解

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# 面向对象编程中非常重要的一部分,尤其在开发 游戏、图形、金融系统、数学计算库 时使用非常广泛。

相关推荐
苏三说技术1 小时前
2026编程圈很火的10个Skills
后端
用户8356290780511 小时前
使用 Python 自动化 Excel 公式和函数:完整指南
后端·python
敲代码的嘎仔2 小时前
实习日志day6--实习日志day6--title命名规范化&businessType纠正&补充缺失的@Log注解&报警与通信模块补充&产出阶段总结文档
java·开发语言·人工智能·git·python·实习·大二
江华森2 小时前
Python 实现高德地图找房(一):环境搭建与数据爬虫
开发语言·爬虫·python
杜子不疼.2 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
编程(变成)小辣鸡2 小时前
Spring事务失效场景
java·后端·spring
PinkSun2 小时前
MySQL 建表报 1030,能查不能建,排查 1 小时发现是我自己改了一行权限
后端
无相求码3 小时前
为什么 printf 可以接受任意数量参数?变长参数的底层真相
后端
郡杰3 小时前
Boot:MP|测验|结果封装|异常处理|前后联调|拦截器
后端