C# 中 Overload(重载)与 Override(重写)的核心区别与实战解析

在 C# 面向对象编程(OOP)中,多态 是三大核心特性之一(封装、继承、多态)。

而在实际编码过程中,Overload(重载)Override(重写) 是最常见、也最容易被混淆的两种"多态体现方式"。

很多初学者会遇到以下困惑:

  • 方法名一样,为什么有时能共存,有时却编译报错?

  • 明明调用的是同一个方法名,运行结果却不一样?

  • virtualoverride 到底解决了什么问题?

本文将从 定义 → 特性 → 代码 → 底层逻辑 → 易错点 五个层次,彻底讲清楚 重载 vs 重写 的本质区别。


一、Overload(重载):同一类内的「静态多态」

1. 什么是方法重载?

方法重载(Overload) 指的是:

同一个类 中,定义多个方法名相同 ,但参数列表不同的方法。

参数列表不同可以体现在:

  • 参数个数不同

  • 参数类型不同

  • 参数顺序不同(不推荐,影响可读性)

⚠️ 注意

仅修改返回值类型,不能构成重载,否则会直接编译报错。


2. 重载的核心特性

重载的本质可以总结为三点:

  • 编译时多态(静态多态)

    在编译阶段,编译器就已经确定要调用哪个方法

  • 不依赖继承

  • 不需要任何关键字(virtual / override)

👉 核心目的

使用"同一个方法名",适配"不同参数场景",提升 API 的可读性与易用性。


3. 重载示例解析

cs 复制代码
class Shape
{
    // 无参数的 Draw
    public virtual void Draw()
    {
        Console.WriteLine("绘制一个形状");
    }

    // 带参数的 Draw ------ 重载
    public void Draw(int size)
    {
        Console.WriteLine($"绘制一个大小为 {size} 的形状");
    }
}

调用时:

cs 复制代码
Shape shape = new Shape();

shape.Draw();     // 匹配 Draw()
shape.Draw(10);   // 匹配 Draw(int)

📌 关键点

调用哪个方法,完全由参数列表决定,与对象运行时类型无关。


二、Override(重写):父子类间的「动态多态」

1. 什么是方法重写?

方法重写(Override) 指的是:

子类对基类中 virtual / abstract 修饰的方法 进行重新实现。

重写必须满足以下条件:

  • ✔️ 存在继承关系

  • ✔️ 基类方法使用 virtualabstract

  • ✔️ 子类方法使用 override

  • ✔️ 方法签名 完全一致(方法名 + 参数列表 + 返回值)


2. 重写的核心特性

  • 运行时多态(动态多态)

  • 行为取决于对象的实际类型

  • ✅ 是 OOP 中多态的核心机制

👉 核心目的

允许子类在不改变调用方式的前提下,定制或替换父类的行为。


3. 重写示例解析

cs 复制代码
class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("绘制一个圆形");
    }
}

关键调用代码:

cs 复制代码
Shape shape = new Circle();
shape.Draw();

📌 重点理解

  • 变量声明类型:Shape

  • 对象实际类型:Circle

  • 运行结果 :调用 Circle.Draw()

这正是动态多态的体现。


三、Overload 与 Override 的核心区别对比

对比维度 Overload(重载) Override(重写)
发生范围 同一个类内部 基类与子类之间
是否依赖继承 ❌ 不需要 ✅ 必须
方法名 相同 相同
参数列表 必须不同 必须完全一致
返回值 不能仅靠返回值区分 必须与基类一致
关键字 virtual / override
多态类型 编译时多态(静态) 运行时多态(动态)
决定时机 编译期 运行期
核心用途 适配不同参数 定制父类行为

四、完整示例:重载 + 重写的组合使用

1. 完整可运行代码

cs 复制代码
using System;

class Shape
{
    // 可被重写的虚方法
    public virtual void Draw()
    {
        Console.WriteLine("绘制一个形状");
    }

    // 重载方法
    public void Draw(int size)
    {
        Console.WriteLine($"绘制一个大小为 {size} 的形状");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("绘制一个圆形");
    }
}

class Program
{
    static void Main()
    {
        Shape shape = new Shape();
        Circle circle = new Circle();

        shape.Draw();       // Shape.Draw()
        shape.Draw(10);     // Shape.Draw(int)

        shape = circle;
        shape.Draw();       // Circle.Draw()
    }
}

2. 程序运行结果

cs 复制代码
绘制一个形状
绘制一个大小为 10 的形状
绘制一个圆形

五、常见误区与踩坑总结

❌ 误区 1:仅修改返回值实现重载

cs 复制代码
int Foo();
string Foo(); // 编译错误

✔️ 原因:返回值不属于方法签名的一部分。


❌ 误区 2:基类没加 virtual,子类却 override

cs 复制代码
class A
{
    public void Test() {}
}

class B : A
{
    public override void Test() {} // 编译错误
}

❌ 误区 3:重写时修改参数列表

cs 复制代码
public override void Draw(int size) // ❌

❌ 误区 4:混淆声明类型与实际类型

cs 复制代码
Shape shape = new Circle();
shape.Draw();

👉 真正决定调用哪个方法的是:new Circle()


六、总结一句话记住区别

重载(Overload)

👉 同一个类中,方法名相同、参数不同编译期决定
重写(Override)

👉 父子类之间,方法签名一致、行为可替换运行期决定

相关推荐
左直拳1 小时前
将c++程序部署到docker
开发语言·c++·docker
崇山峻岭之间1 小时前
Matlab学习记录31
开发语言·学习·matlab
bugcome_com1 小时前
C# 字符串拼接全面指南
c#·.net·wpf
你怎么知道我是队长2 小时前
C语言---输入和输出
c语言·开发语言
mmz12072 小时前
二分查找(c++)
开发语言·c++·算法
你怎么知道我是队长2 小时前
C语言---文件读写
java·c语言·开发语言
陌路202 小时前
C++30 STL容器 -deque双端队列
开发语言·c++
xb11322 小时前
C#委托详解
开发语言·c#
brent4232 小时前
DAY50复习日
开发语言·python
木头程序员2 小时前
前端(包含HTML/JavaScript/DOM/BOM/jQuery)基础-暴力复习篇
开发语言·前端·javascript·ecmascript·es6·jquery·html5