第 5 课 · 约 12 分钟 · ← 第 4 课
方法:给菜谱起名字
方法是一段有名字的代码块,带输入(参数),通常有一个输出(返回值)。菜谱写一次,处处可用。
return:回答问题的方法
int Add(int a, int b)
{
return a + b; // 把这个值交还给调用方
}
Console.WriteLine(Add(3, 4));
签名从左往右读:int(返回什么)Add(叫什么)(int a, int b)(要什么)。调用处的 Add(3, 4) 就是值 7——它可以去任何值能去的地方。
void:做事的方法,不回答问题
void Greet(string name)
{
Console.WriteLine("Hello, " + name + "!");
}
Greet("Ada");
Greet("Grace");
void 表示"什么都不返回"——方法做完事,控制权回到调用方。需要提前离场时,不带值的 return; 也可以。
多个 return,一个答案
方法返回它碰到的第一个 return——提前返回胜过深层嵌套:
string Describe(int score)
{
if (score >= 90) return "excellent";
if (score >= 70) return "good";
return "keep practicing";
}
Console.WriteLine(Describe(95));
Console.WriteLine(Describe(75));
Console.WriteLine(Describe(30));
默认值:可选参数
void Greet(string name, string greeting = "Hello")
{
Console.WriteLine(greeting + ", " + name + "!");
}
Greet("Ada"); // greeting 用默认值
Greet("Bob", "Hi"); // 也可以覆盖
out:一个方法回答两个问题
return 只能给你一个值。当一个方法既要产出值又要报告成败——int.TryParse 背后的现实模式——用 out:
bool TryDouble(int x, out int doubled)
{
doubled = x * 2; // 方法必须给 out 参数赋值
return x < 100; // ……并报告这个值能不能用
}
if (TryDouble(21, out int result))
{
Console.WriteLine("doubled: " + result);
}
递归:调用自己的方法
int Fib(int n)
{
if (n < 2) return n; // 基线条件:终止自调用
return Fib(n - 1) + Fib(n - 2);
}
Console.Write(Fib(10));
每个递归都要有基线条件(停止条件)——没有它,调用永不结束,你会得到 StackOverflowException。这里的引擎在约 900 层嵌套时拦停你,和真实运行时同一个思路。
参数出错的样子
参数个数给错,编译器在任何东西运行前就拦住你——你会看到 CS1501 / CS7036,参数数量不匹配是它们最常见的触发器。
现在就练
- 用第 4 课的"运行最大值"模式写
int Max3(int a, int b, int c)——一个return,不用库。然后去判题对答案。 - 用
% 10 / 10循环写int SumDigits(int n)——把数位数的模式包成方法。 - 下一课:第 6 课 — 类与对象,方法从此有了家。