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

相关推荐
Wang's Blog4 小时前
Go-Zero 项目开发43:基于 Filebeat 收集各个服务的日志信息
开发语言·golang·go-zero·filebeat
2601_953720824 小时前
【计算机毕业设计】基于Spring Boot的心理健康咨询与评测系统的设计与实现
java·spring boot·后端
丈剑走天涯5 小时前
JDK 17 正式特性
java·开发语言
东方小月5 小时前
从零开发一个 Coding Agent(四):使用状态机校验大模型事件流
前端·人工智能·后端
秋田君6 小时前
QT_QFontDialog类字体对话框
开发语言·qt
圣光SG6 小时前
Java操作题练习(七)
java·开发语言·算法
都叫我大帅哥6 小时前
“让AI修就行”?我劝你收回这句话——来自一位Java博主的硬核反常识
后端
whyfail6 小时前
前端学 Spring Boot(8):接口为什么越用越慢?
前端·spring boot·后端
麻瓜老宋7 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十三步,多行输入、进制输出、错误恢复、常量折叠、配置加载等
c语言·开发语言·atomcode