方法(定义/调用/重载)
本教程共 100 篇 · 第 30 篇 · 更新于 2026-07-31 · 约 8 分钟阅读
30. 方法(定义/调用/重载)
本节目标:会定义带参数和返回值的方法,理解方法签名,并掌握同名方法重载。
什么是方法
方法(method)是把一组相关语句打包、完成一个明确任务的代码块。它干了两件事:让代码能复用(写一次、到处调用),让逻辑更清晰(每段代码各管一摊事)。在面向对象里,方法就是”对象的行为”的载体。
方法的基本结构
一个方法由四部分组成:返回类型、名称、参数列表、方法体。
namespace CSharpDemo;
int Add(int a, int b)
{
return a + b;
}
Console.WriteLine(Add(2, 3)); // 5
这里 Add 是个顶级局部函数(local function),用来演示”返回类型 + 名称 + 参数列表 + 方法体”四件套。放进类里时结构完全一样,只是多了一个所属的类。
Note不返回值就用
void。返回类型 + 方法名 + 参数列表,三者合起来叫”方法签名(signature)“。编译器主要靠签名区分不同方法,调用时按签名找到对应的那个。
定义与调用(在类中)
先写使用,再看类定义:
namespace CSharpDemo;
Calculator calc = new();
int result = calc.Add(3, 5);
Console.WriteLine(result); // 8
class Calculator
{
public int Add(int a, int b) => a + b;
}
calc.Add(3, 5) 里 3、5 是实参(argument),对应定义里的形参(parameter)a、b。
参数与返回值
参数是方法的”输入”,用”类型 + 名称”声明;返回值是”输出”,用 return 交回调用方。
namespace CSharpDemo;
string Greet(string name) => $"你好,{name}";
Console.WriteLine(Greet("小明")); // 你好,小明
Warning声明了非
void返回类型却在某分支漏写return,编译直接报错。务必保证”所有执行路径”都有返回值。比如if里return了,但else分支漏了就不行。
表达式体方法
当方法体只有一句话(尤其是一句 return),可用 => 写成表达式体(expression-bodied member),更紧凑:
int Add(int a, int b) => a + b;
string Greet(string name) => $"你好,{name}";
这种写法从 C# 6 起就支持,方法、属性、构造器等都能用。它不改变行为,只是让短方法更顺眼。
参数个数可变:params(预告)
有时参数个数不固定,可用 params 关键字接收一批同类型参数。这里先留个印象,后面有专章细讲。
namespace CSharpDemo;
int Sum(params int[] values)
{
int total = 0;
foreach (var v in values) total += v;
return total;
}
Console.WriteLine(Sum(1, 2, 3)); // 6
Console.WriteLine(Sum(1, 2, 3, 4)); // 10
方法重载(overload)
同一个类(或同一个作用域)里可以有多个同名方法,只要参数列表不同(数量、类型或顺序不同),这叫重载(overload)。
namespace CSharpDemo;
Calculator calc = new();
Console.WriteLine(calc.Add(1, 2)); // 3
Console.WriteLine(calc.Add(1, 2, 3)); // 6
Console.WriteLine(calc.Add(1.5, 2.5)); // 4.0
class Calculator
{
public int Add(int a, int b) => a + b;
public int Add(int a, int b, int c) => a + b + c;
public double Add(double a, double b) => a + b;
}
Note重载只看参数列表,不看返回类型。两个方法仅返回类型不同、参数完全一样,不算重载,会编译冲突。判断重载靠”签名里的参数部分”。
重载解决了什么
没有重载时,你只能起 AddInt、AddDouble、AddThree 这种名字,调用方得记一长串。重载让”同一个意图”共用一个名字,编译器按你传的实参自动挑选最合适那一个,调用更自然,API 也更干净。
// 没有重载:名字一长串,难记
int AddInt(int a, int b) => a + b;
double AddDouble(double a, double b) => a + b;
// 有重载:一个 Add 搞定
int Add(int a, int b) => a + b;
double Add(double a, double b) => a + b;
Tip重载的匹配规则:实参能唯一对应某个版本就选它;若多个版本都”说得通”,编译器选最具体的那个(比如
Add(int, int)比Add(double, double)更贴合两个整数实参),仍选不出就报”调用不明确”。
一个真实场景
打印日志的方法,可能只传一条消息,也可能同时传消息和级别。用重载就很自然:
namespace CSharpDemo;
void Log(string message) =>
Console.WriteLine($"[INFO] {message}");
void Log(string message, string level) =>
Console.WriteLine($"[{level}] {message}");
Log("启动完成");
Log("出错了", "ERROR");
什么时候该抽出方法
- 一段逻辑在多处重复 → 抽成方法复用。
- 一个方法长到看不完(几十行)→ 拆成几个小方法,各管一摊。
- 某段代码能用”一个动作名”概括(如
CalculateTotal、ValidateInput)→ 抽出来,主流程读起来像讲故事。
相反,只在一处用、且只有两三行,是否抽方法看个人喜好,不必强行拆分。
Tip方法命名用”动词开头”的动宾短语(
GetUser、SaveOrder),一眼就知道它做什么、返回什么。好名字胜过一堆注释。
方法 vs 局部函数
如果一段逻辑只在某个方法内部用、且不需要对外,C# 还支持”局部函数(local function)“——直接写在方法体内。它和重载不冲突,只是作用域更小、外面看不见。初学先掌握普通方法,局部函数后面章节会讲。两者选择原则很简单:要被多处或外部调用就写成方法,只在一个方法里用就写成局部函数。
常见坑
- 忘了 return:非
void方法某条分支没返回,编译报错。 - 以为返回类型能区分重载:仅返回类型不同不算重载,编译冲突。
- 重载歧义:传入
Add(1, 1)若同时有Add(int, int)与Add(double, double),编译器会选更具体的int版;若你定义了两种都”说得通”的版本,可能报”调用不明确”。 - 方法太长:一个方法塞太多事,又难读又难测。该拆就拆。
最佳实践
- 一个方法只做一件事(单一职责),名字说清这件事。
- 短方法用表达式体
=>,长方法用完整语句体。 - 合理用重载让 API 更自然,但别为了重载而堆出十几个几乎一样的版本。
- 非
void方法保证所有路径都有返回值;void方法用return;提前退出也没问题。 - 参数多到记不住时,考虑用对象/记录(record)打包参数,或拆方法。
方法返回多个值怎么办
有时一个方法想返回两样东西,比如”既算总价又算折扣”。除了定义新类,C# 还支持元组(tuple)一次性返回多个值,写法很轻巧:
namespace CSharpDemo;
(int total, int discount) Calc(int price, int count)
{
int t = price * count;
return (t, t / 10);
}
var r = Calc(100, 3);
Console.WriteLine($"总价{r.total} 折扣{r.discount}");
Note元组是 C# 7 起的特性,适合”临时凑一组返回值”。如果这组值要反复传递、有名字意义,定义一个
record或类会更清晰。这里先看个样子,元组后面章节会细讲。
void 方法也能提前退出
void 方法没有返回值,但可以用 return; 提前结束,常用于”不满足条件就直接走人”的卫语句风格:
void PrintIfPositive(int n)
{
if (n <= 0) return; // 不满足就退出
Console.WriteLine(n);
}
Tip早点
return能把异常分支挡在前面,主逻辑保持平整,比层层if包住所有代码更好读。
写方法的一点心法
方法名本身就是文档。一个好的名字(如 CalculateTotal、IsValid)让调用处读起来像人话,别人不必点进去看实现。反之,叫 Do1、Handle 这种模糊名字,三个月后连你自己都看不懂。
Tip如果一个方法名需要加”和”才能说清它干啥(如”校验并保存并发邮件”),说明它做了太多事,该拆成几个方法了。单一职责的方法才好测、好复用。
小结
方法是代码复用的核心。方法签名 = 返回类型 + 名称 + 参数。重载让同名方法按参数不同共存,是 API 设计里极常用的技巧。下一篇我们讲构造函数,看对象出生时如何被初始化。