C# 零基础到精通教程 - 第六章:方法——让代码“模块化“
6.1 为什么需要方法?
6.1.1 没有方法的问题
csharp
// 没有方法:代码重复、臃肿、难以维护
static void Main()
{
// 第一次计算两个数的和
int a1 = 10, b1 = 20;
int sum1 = a1 + b1;
Console.WriteLine($"{a1} + {b1} = {sum1}");
// 第二次计算两个数的和
int a2 = 15, b2 = 25;
int sum2 = a2 + b2;
Console.WriteLine($"{a2} + {b2} = {sum2}");
// 第三次...
// 每次都要重复写同样的代码
}
6.1.2 有方法的解决方案
csharp
// 定义一个方法,封装"加法并输出"的功能
static void AddAndPrint(int a, int b)
{
int sum = a + b;
Console.WriteLine($"{a} + {b} = {sum}");
}
static void Main()
{
AddAndPrint(10, 20); // 一行代码解决问题
AddAndPrint(15, 25);
AddAndPrint(100, 200);
}
6.1.3 方法的定义
方法 = 一个具有名称的代码块,用于执行特定任务
text
方法的比喻: ┌─────────────────────────────────────────────────────────┐ │ 餐厅的"做菜"流程 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 点菜单(参数) 菜品(返回值) │ │ ↓ ↑ │ │ ┌─────────────────────────────────────┐ │ │ │ 做菜方法 │ │ │ │ 1. 洗菜 │ │ │ │ 2. 切菜 │ │ │ │ 3. 炒菜 │ │ │ │ 4. 调味 │ │ │ │ 5. 装盘 │ │ │ └─────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘
6.2 方法的声明和调用
6.2.1 方法的基本语法
csharp
// 语法
[访问修饰符] [static] 返回值类型 方法名(参数列表)
{
// 方法体:执行的代码
return 返回值; // 如果返回值类型不是 void,必须有 return
}
// 最简单的无参无返回值方法
static void SayHello()
{
Console.WriteLine("Hello!");
}
// 有参数无返回值
static void Greet(string name)
{
Console.WriteLine($"你好,{name}!");
}
// 有参数有返回值
static int Add(int a, int b)
{
return a + b;
}
6.2.2 方法的各个部分
csharp
// 完整示例
static int CalculateSum(int start, int end)
// ↑ ↑ ↑ ↑ ↑
// 修饰符 返回值类型 方法名 参数1 参数2
{
int sum = 0;
for (int i = start; i <= end; i++)
{
sum += i;
}
return sum; // 返回计算结果
}
各部分详解:
| 部分 | 说明 | 示例 |
|---|---|---|
static |
静态方法,可以直接通过类名调用 | static |
| 返回值类型 | 方法返回什么类型的数据,如果不返回用 void |
int, string, double, void |
| 方法名 | 标识方法,使用 PascalCase 命名规范 | CalculateSum, GetName |
| 参数列表 | 传入方法的数据,可以有多个,用逗号分隔 | (int a, string b) |
| 方法体 | 花括号内的代码 | { ... } |
return |
返回值并结束方法 | return sum; |
6.2.3 调用方法
csharp
static void Main()
{
// 调用无返回值方法
SayHello();
// 调用有参数方法
Greet("张三");
// 调用有返回值方法
int result = Add(5, 3);
Console.WriteLine($"5 + 3 = {result}");
// 也可以直接使用返回值
Console.WriteLine($"10 + 20 = {Add(10, 20)}");
}
6.2.4 方法的执行流程
text
Main 方法:
┌─────────────────────────────────────────┐
│ int result = Add(5, 3); │
│ │ │
│ │ 调用 Add 方法 │
│ ↓ │
└───────┼─────────────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ static int Add(int a, int b) │
│ { │
│ // a = 5, b = 3 │
│ int sum = a + b; // sum = 8 │
│ return sum; // 返回 8 │
│ } │
└───────┬─────────────────────────────────┘
│
│ 返回值 8
↓
┌─────────────────────────────────────────┐
│ int result = 8; │
└─────────────────────────────────────────┘
6.3 方法的参数
6.3.1 参数的基本使用
csharp
// 单个参数
static void PrintSquare(int number)
{
Console.WriteLine($"{number} 的平方是 {number * number}");
}
// 多个参数
static double CalculateRectangleArea(double width, double height)
{
return width * height;
}
// 调用
PrintSquare(5); // 输出:5 的平方是 25
double area = CalculateRectangleArea(10.5, 20.3);
6.3.2 参数的传递机制
值类型参数传递的是值的副本,方法内修改不影响原变量
csharp
static void ChangeValue(int x)
{
x = 100; // 修改的是副本
Console.WriteLine($"方法内部:x = {x}");
}
static void Main()
{
int a = 10;
ChangeValue(a);
Console.WriteLine($"方法外部:a = {a}");
}
// 输出:
// 方法内部:x = 100
// 方法外部:a = 10 ← 没有改变!
6.3.3 ref 参数(引用传递)
使用 ref 关键字,传递的是变量的引用,方法内修改会影响原变量
csharp
static void ChangeValueByRef(ref int x)
{
x = 100; // 修改的是原变量
Console.WriteLine($"方法内部:x = {x}");
}
static void Main()
{
int a = 10;
ChangeValueByRef(ref a); // 调用时也要写 ref
Console.WriteLine($"方法外部:a = {a}");
}
// 输出:
// 方法内部:x = 100
// 方法外部:a = 100 ← 被改变了!
6.3.4 out 参数(输出参数)
out 参数用于从方法返回多个值,调用前不需要初始化
csharp
// 返回多个值:商和余数
static void Divide(int dividend, int divisor, out int quotient, out int remainder)
{
quotient = dividend / divisor;
remainder = dividend % divisor;
}
// 经典的 TryParse 模式
static bool TryParseToInt(string input, out int result)
{
try
{
result = Convert.ToInt32(input);
return true;
}
catch
{
result = 0;
return false;
}
}
static void Main()
{
// 使用 out 参数
int q, r;
Divide(17, 5, out q, out r);
Console.WriteLine($"17 ÷ 5 = {q} 余 {r}"); // 17 ÷ 5 = 3 余 2
// TryParse 模式
string input = "123abc";
if (TryParseToInt(input, out int number))
{
Console.WriteLine($"转换成功:{number}");
}
else
{
Console.WriteLine("转换失败");
}
}
6.3.5 ref vs out 对比
| 特点 | ref | out |
|---|---|---|
| 传入前是否需要初始化 | 需要 | 不需要 |
| 方法内是否必须赋值 | 不必 | 必须(返回前要赋值) |
| 用途 | 修改传入的变量 | 返回额外的值 |
| 调用时写法 | ref 关键字 |
out 关键字 |
csharp
// ref:传入前必须初始化 int refValue = 10; // 必须初始化 MethodWithRef(ref refValue); // out:传入前不需要初始化 int outValue; // 可以不初始化 MethodWithOut(out outValue); // 方法内必须赋值
6.3.6 默认参数(可选参数)
csharp
// 带默认值的参数必须放在参数列表的最后
static void Greet(string name, string greeting = "你好")
{
Console.WriteLine($"{greeting},{name}!");
}
static void Main()
{
Greet("张三"); // 使用默认值:你好,张三!
Greet("李四", "晚上好"); // 使用传入值:晚上好,李四!
}
6.3.7 命名参数
调用时可以指定参数名称,不按位置传递
csharp
static void PrintPersonInfo(string name, int age, string city)
{
Console.WriteLine($"姓名:{name},年龄:{age},城市:{city}");
}
static void Main()
{
// 位置参数(按顺序)
PrintPersonInfo("张三", 25, "北京");
// 命名参数(可以不按顺序)
PrintPersonInfo(city: "上海", name: "李四", age: 30);
// 混合使用(位置参数必须在命名参数之前)
PrintPersonInfo("王五", city: "广州", age: 28);
}
6.4 方法的返回值
6.4.1 返回值的基本使用
csharp
// 返回 int 类型
static int GetMax(int a, int b)
{
if (a > b)
return a;
else
return b;
}
// 返回 string 类型
static string GetGreeting(string name)
{
return $"你好,{name}!欢迎回来。";
}
// 返回 bool 类型
static bool IsAdult(int age)
{
return age >= 18;
}
// 调用
int max = GetMax(10, 20);
string greeting = GetGreeting("张三");
bool canVote = IsAdult(18);
6.4.2 void 方法(无返回值)
csharp
// void 表示不返回任何值
static void PrintBanner()
{
Console.WriteLine("******************");
Console.WriteLine("* 欢迎来到C#世界 *");
Console.WriteLine("******************");
}
// 调用
PrintBanner();
// void 方法也可以使用 return(但不能返回值),用于提前结束
static void PrintNumbers(int max)
{
if (max <= 0)
{
Console.WriteLine("参数无效");
return; // 提前结束
}
for (int i = 1; i <= max; i++)
{
Console.Write(i + " ");
}
Console.WriteLine();
}
6.4.3 返回数组
csharp
// 返回一个整型数组
static int[] GenerateRandomArray(int length, int min, int max)
{
Random random = new Random();
int[] array = new int[length];
for (int i = 0; i < length; i++)
{
array[i] = random.Next(min, max + 1);
}
return array;
}
// 调用
int[] numbers = GenerateRandomArray(10, 1, 100);
Console.WriteLine($"随机数组:{string.Join(", ", numbers)}");
6.4.4 返回多个值(使用元组)
C# 7.0+ 支持元组语法,可以轻松返回多个值
csharp
// 使用元组返回多个值
static (int sum, int count, double average) CalculateStats(int[] numbers)
{
int sum = 0;
foreach (int num in numbers)
{
sum += num;
}
int count = numbers.Length;
double average = count > 0 ? (double)sum / count : 0;
return (sum, count, average);
}
static void Main()
{
int[] scores = { 85, 92, 78, 90, 88 };
// 接收元组返回值
(int total, int num, double avg) = CalculateStats(scores);
Console.WriteLine($"总数:{total}");
Console.WriteLine($"个数:{num}");
Console.WriteLine($"平均:{avg:F2}");
// 也可以单独接收
var stats = CalculateStats(scores);
Console.WriteLine($"总和:{stats.sum}");
Console.WriteLine($"平均:{stats.average:F2}");
}
6.5 方法的重载
6.5.1 什么是方法重载?
同一个类中,多个方法可以使用相同的名字,只要参数列表不同
csharp
// 同一个方法名 Add,不同的参数
static int Add(int a, int b)
{
return a + b;
}
static double Add(double a, double b)
{
return a + b;
}
static int Add(int a, int b, int c)
{
return a + b + c;
}
static string Add(string a, string b)
{
return a + b;
}
// 调用时,编译器根据传入的参数自动选择合适的方法
static void Main()
{
Console.WriteLine(Add(5, 3)); // 调用 int Add(int, int)
Console.WriteLine(Add(5.5, 3.2)); // 调用 double Add(double, double)
Console.WriteLine(Add(1, 2, 3)); // 调用 int Add(int, int, int)
Console.WriteLine(Add("Hello", " World")); // 调用 string Add(string, string)
}
6.5.2 重载的规则
可以重载的情况:
csharp
// 1. 参数个数不同
void Print(int a) { }
void Print(int a, int b) { }
// 2. 参数类型不同
void Print(int a) { }
void Print(string a) { }
// 3. 参数顺序不同
void Print(int a, string b) { }
void Print(string a, int b) { }
不能重载的情况:
csharp
// ❌ 只有返回值类型不同,不能重载
int GetValue() { return 0; }
string GetValue() { return ""; } // 编译错误
// ❌ 只有参数名称不同,不能重载
void Print(int x) { }
void Print(int y) { } // 编译错误
// ❌ 只有 ref/out 区别,不能重载
void Process(ref int x) { }
void Process(out int x) { } // 编译错误
6.5.3 重载的实际应用:Console.WriteLine
csharp
// Console.WriteLine 有 19 个重载版本
Console.WriteLine(); // 输出空行
Console.WriteLine("Hello"); // 输出字符串
Console.WriteLine(123); // 输出整数
Console.WriteLine(3.14); // 输出小数
Console.WriteLine(true); // 输出布尔值
Console.WriteLine("{0} + {1} = {2}", 1, 2, 3); // 格式化输出
6.6 方法的递归
6.6.1 什么是递归?
递归 = 方法调用自身
csharp
// 递归的经典例子:阶乘
// n! = n × (n-1) × (n-2) × ... × 1
static int Factorial(int n)
{
// 终止条件:基础情况
if (n <= 1)
return 1;
// 递归调用:n! = n × (n-1)!
return n * Factorial(n - 1);
}
// 执行过程:Factorial(5)
// Factorial(5) = 5 × Factorial(4)
// Factorial(4) = 4 × Factorial(3)
// Factorial(3) = 3 × Factorial(2)
// Factorial(2) = 2 × Factorial(1)
// Factorial(1) = 1
// 然后逐层返回:2×1=2, 3×2=6, 4×6=24, 5×24=120
6.6.2 递归的必要条件
csharp
// 递归必须满足:
// 1. 有终止条件(防止无限递归)
// 2. 每次递归调用都向终止条件靠近
// ✅ 正确示例:斐波那契数列
static int Fibonacci(int n)
{
if (n <= 1) return n; // 终止条件
return Fibonacci(n - 1) + Fibonacci(n - 2); // 向终止条件靠近
}
// ❌ 错误示例:没有终止条件
static void InfiniteRecursion()
{
Console.WriteLine("无限递归");
InfiniteRecursion(); // 栈溢出!
}
6.6.3 递归的应用场景
csharp
// 1. 遍历文件夹(目录树)
static void PrintDirectory(string path, int level = 0)
{
string indent = new string(' ', level * 2);
Console.WriteLine($"{indent}📁 {Path.GetFileName(path)}");
try
{
// 遍历子目录
foreach (string dir in Directory.GetDirectories(path))
{
PrintDirectory(dir, level + 1);
}
// 遍历文件
foreach (string file in Directory.GetFiles(path))
{
Console.WriteLine($"{indent} 📄 {Path.GetFileName(file)}");
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine($"{indent} [无权限]");
}
}
// 2. 汉诺塔问题
static void Hanoi(int n, char from, char to, char helper)
{
if (n == 1)
{
Console.WriteLine($"移动盘子 1 从 {from} 到 {to}");
return;
}
Hanoi(n - 1, from, helper, to);
Console.WriteLine($"移动盘子 {n} 从 {from} 到 {to}");
Hanoi(n - 1, helper, to, from);
}
6.6.4 递归 vs 循环
| 特点 | 递归 | 循环 |
|---|---|---|
| 代码简洁性 | 适合树形结构 | 适合线性问题 |
| 性能 | 较差(有函数调用开销) | 较好 |
| 内存使用 | 多(每次调用占用栈空间) | 少 |
| 风险 | 可能栈溢出 | 可能死循环 |
| 可读性 | 自然递归逻辑 | 需要手动维护状态 |
csharp
// 递归:代码简洁但性能差
static int SumRecursive(int n)
{
if (n <= 0) return 0;
return n + SumRecursive(n - 1);
}
// 循环:性能好但需要手动控制
static int SumLoop(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
6.7 局部函数(C# 7.0+)
在方法内部定义的方法,只能在所在方法内部使用
csharp
static void ProcessData(int[] numbers)
{
// 局部函数
bool IsEven(int n)
{
return n % 2 == 0;
}
int Square(int n)
{
return n * n;
}
// 使用局部函数
foreach (int num in numbers)
{
if (IsEven(num))
{
Console.WriteLine($"{num} 是偶数,平方是 {Square(num)}");
}
}
}
static void Main()
{
int[] data = { 1, 2, 3, 4, 5 };
ProcessData(data);
// IsEven(10); // ❌ 错误:局部函数外部不可见
}
局部函数的优势:
-
限制作用域,只在需要的地方可见
-
可以访问外部方法的局部变量
-
适合递归(比 lambda 表达式更清晰)
6.8 综合示例
示例1:数学工具类
csharp
using System;
class MathTools
{
// 判断是否为质数
static bool IsPrime(int number)
{
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
int limit = (int)Math.Sqrt(number);
for (int i = 3; i <= limit; i += 2)
{
if (number % i == 0) return false;
}
return true;
}
// 获取最大公约数(欧几里得算法)
static int GCD(int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// 获取最小公倍数
static int LCM(int a, int b)
{
return a * b / GCD(a, b);
}
// 判断是否为回文数
static bool IsPalindrome(int number)
{
string str = number.ToString();
int left = 0, right = str.Length - 1;
while (left < right)
{
if (str[left] != str[right]) return false;
left++;
right--;
}
return true;
}
static void Main()
{
Console.WriteLine($"17 是质数吗?{IsPrime(17)}");
Console.WriteLine($"24 和 36 的最大公约数:{GCD(24, 36)}");
Console.WriteLine($"24 和 36 的最小公倍数:{LCM(24, 36)}");
Console.WriteLine($"12321 是回文数吗?{IsPalindrome(12321)}");
}
}
示例2:学生管理系统的完整实现
csharp
using System;
class StudentManager
{
static string[] names = new string[100];
static int[] scores = new int[100];
static int studentCount = 0;
static void Main()
{
bool running = true;
while (running)
{
ShowMenu();
string choice = Console.ReadLine();
switch (choice)
{
case "1":
AddStudent();
break;
case "2":
ShowAllStudents();
break;
case "3":
ShowStatistics();
break;
case "4":
SearchStudent();
break;
case "5":
SortByScore();
break;
case "6":
running = false;
Console.WriteLine("感谢使用,再见!");
break;
default:
Console.WriteLine("无效选择,请重新输入!");
break;
}
if (running && choice != "6")
{
Console.WriteLine("\n按任意键继续...");
Console.ReadKey();
}
}
}
static void ShowMenu()
{
Console.Clear();
Console.WriteLine("=== 学生管理系统 ===");
Console.WriteLine("1. 添加学生");
Console.WriteLine("2. 查看所有学生");
Console.WriteLine("3. 统计信息");
Console.WriteLine("4. 查找学生");
Console.WriteLine("5. 按成绩排序");
Console.WriteLine("6. 退出");
Console.Write("请选择:");
}
static void AddStudent()
{
if (studentCount >= names.Length)
{
Console.WriteLine("学生数量已达上限!");
return;
}
Console.Write("请输入学生姓名:");
string name = Console.ReadLine();
Console.Write("请输入学生成绩:");
if (!int.TryParse(Console.ReadLine(), out int score))
{
Console.WriteLine("成绩输入无效!");
return;
}
names[studentCount] = name;
scores[studentCount] = score;
studentCount++;
Console.WriteLine($"成功添加学生:{name},成绩:{score}");
}
static void ShowAllStudents()
{
if (studentCount == 0)
{
Console.WriteLine("暂无学生数据!");
return;
}
Console.WriteLine("\n所有学生列表:");
Console.WriteLine("序号\t姓名\t成绩");
Console.WriteLine("-----------------");
for (int i = 0; i < studentCount; i++)
{
Console.WriteLine($"{i + 1}\t{names[i]}\t{scores[i]}");
}
}
static void ShowStatistics()
{
if (studentCount == 0)
{
Console.WriteLine("暂无学生数据!");
return;
}
int sum = 0, max = scores[0], min = scores[0];
string maxName = names[0], minName = names[0];
int passCount = 0, failCount = 0;
for (int i = 0; i < studentCount; i++)
{
sum += scores[i];
if (scores[i] > max)
{
max = scores[i];
maxName = names[i];
}
if (scores[i] < min)
{
min = scores[i];
minName = names[i];
}
if (scores[i] >= 60) passCount++;
else failCount++;
}
double average = (double)sum / studentCount;
Console.WriteLine("\n=== 统计信息 ===");
Console.WriteLine($"学生总数:{studentCount}");
Console.WriteLine($"总分:{sum}");
Console.WriteLine($"平均分:{average:F2}");
Console.WriteLine($"最高分:{max}({maxName})");
Console.WriteLine($"最低分:{min}({minName})");
Console.WriteLine($"及格人数:{passCount},及格率:{(double)passCount / studentCount * 100:F1}%");
Console.WriteLine($"不及格人数:{failCount},不及格率:{(double)failCount / studentCount * 100:F1}%");
// 成绩分布
int[] levelCount = new int[5]; // A,B,C,D,F
for (int i = 0; i < studentCount; i++)
{
if (scores[i] >= 90) levelCount[0]++;
else if (scores[i] >= 80) levelCount[1]++;
else if (scores[i] >= 70) levelCount[2]++;
else if (scores[i] >= 60) levelCount[3]++;
else levelCount[4]++;
}
Console.WriteLine("\n成绩分布:");
Console.WriteLine($"A (90-100):{levelCount[0]}人");
Console.WriteLine($"B (80-89):{levelCount[1]}人");
Console.WriteLine($"C (70-79):{levelCount[2]}人");
Console.WriteLine($"D (60-69):{levelCount[3]}人");
Console.WriteLine($"F (<60):{levelCount[4]}人");
}
static void SearchStudent()
{
if (studentCount == 0)
{
Console.WriteLine("暂无学生数据!");
return;
}
Console.Write("请输入要查找的学生姓名:");
string searchName = Console.ReadLine();
bool found = false;
for (int i = 0; i < studentCount; i++)
{
if (names[i].Equals(searchName, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"找到学生:{names[i]},成绩:{scores[i]}");
found = true;
}
}
if (!found)
{
Console.WriteLine($"未找到名为“{searchName}”的学生。");
}
}
static void SortByScore()
{
if (studentCount <= 1)
{
ShowAllStudents();
return;
}
// 冒泡排序(按成绩降序)
for (int i = 0; i < studentCount - 1; i++)
{
for (int j = 0; j < studentCount - i - 1; j++)
{
if (scores[j] < scores[j + 1])
{
// 交换成绩
int tempScore = scores[j];
scores[j] = scores[j + 1];
scores[j + 1] = tempScore;
// 同时交换姓名
string tempName = names[j];
names[j] = names[j + 1];
names[j + 1] = tempName;
}
}
}
Console.WriteLine("\n已按成绩从高到低排序:");
ShowAllStudents();
}
}
示例3:猜数字游戏(方法版)
csharp
using System;
class GuessNumberGame
{
static Random random = new Random();
static int secretNumber;
static int attempts;
static int maxAttempts = 10;
static void Main()
{
bool playAgain = true;
while (playAgain)
{
InitializeGame();
PlayGame();
playAgain = AskPlayAgain();
}
Console.WriteLine("感谢游玩,再见!");
}
static void InitializeGame()
{
secretNumber = random.Next(1, 101);
attempts = 0;
Console.Clear();
Console.WriteLine("=== 猜数字游戏 ===");
Console.WriteLine($"我已经想好了一个1-100之间的数字。");
Console.WriteLine($"你有{maxAttempts}次机会猜中它!");
Console.WriteLine();
}
static void PlayGame()
{
bool guessed = false;
while (attempts < maxAttempts && !guessed)
{
int guess = GetPlayerGuess();
attempts++;
guessed = CheckGuess(guess);
if (!guessed && attempts < maxAttempts)
{
GiveHint(guess);
}
}
ShowResult(guessed);
}
static int GetPlayerGuess()
{
int guess;
bool validInput = false;
do
{
Console.Write($"请输入你的猜测(剩余{maxAttempts - attempts}次机会):");
string input = Console.ReadLine();
if (int.TryParse(input, out guess) && guess >= 1 && guess <= 100)
{
validInput = true;
}
else
{
Console.WriteLine("请输入1-100之间的有效数字!");
}
} while (!validInput);
return guess;
}
static bool CheckGuess(int guess)
{
if (guess == secretNumber)
{
Console.WriteLine($"\n🎉 恭喜!你用了{attempts}次猜中了数字{secretNumber}!");
return true;
}
return false;
}
static void GiveHint(int guess)
{
if (guess < secretNumber)
{
Console.WriteLine("太小了,再试试更大的数字!");
}
else
{
Console.WriteLine("太大了,再试试更小的数字!");
}
// 提供距离提示
int difference = Math.Abs(secretNumber - guess);
if (difference <= 5)
{
Console.WriteLine("🔥 非常接近了!");
}
else if (difference <= 10)
{
Console.WriteLine("⭐ 比较接近了!");
}
}
static void ShowResult(bool guessed)
{
if (guessed)
{
// 根据猜中次数给出评价
if (attempts <= 3)
Console.WriteLine("🏆 天才!你是个猜数字高手!");
else if (attempts <= 7)
Console.WriteLine("👍 不错哦!继续加油!");
else
Console.WriteLine("😊 恭喜!下次可以尝试更快猜中!");
}
else
{
Console.WriteLine($"\n😭 很遗憾,机会用完了!");
Console.WriteLine($"正确答案是:{secretNumber}");
}
}
static bool AskPlayAgain()
{
Console.Write("\n是否继续游戏?(y/n):");
string response = Console.ReadLine()?.ToLower();
return response == "y" || response == "yes";
}
}
6.9 常见错误与陷阱
错误1:返回值类型不匹配
csharp
static int GetNumber()
{
return "123"; // ❌ 不能返回 string
}
static int GetNumber()
{
// 没有 return 语句 // ❌ 非 void 方法必须有 return
}
错误2:方法内代码不可达
csharp
static void Test()
{
return;
Console.WriteLine("这行永远不会执行"); // ❌ 警告:不可达代码
}
错误3:递归没有终止条件
csharp
static void EndlessRecursion()
{
EndlessRecursion(); // ❌ 栈溢出异常
}
错误4:ref/out 使用错误
csharp
static void Method(ref int x) { }
int a;
Method(ref a); // ❌ ref 参数必须初始化
static void Method2(out int x) { }
int b = 10;
Method2(out b); // out 参数不要求初始化,但初始值会被忽略
6.10 本章总结
方法设计原则
| 原则 | 说明 |
|---|---|
| 单一职责 | 一个方法只做一件事 |
| 方法名有意义 | 方法名应该清楚表达功能 |
| 参数不要太多 | 建议不超过5个参数 |
| 代码不要过长 | 建议不超过50行 |
| 避免副作用 | 方法应该只做名称所描述的事 |
方法签名
方法签名 = 方法名 + 参数类型和顺序(不包括返回值类型)
csharp
void Print(int a) // 签名:Print(int) void Print(string s) // 签名:Print(string) int Print(int a) // ❌ 与第一个冲突,只有返回值不同
本章核心知识点
text
方法 ├── 定义:static 返回值类型 方法名(参数列表) ├── 调用:方法名(参数) ├── 返回值:return 值(void 无返回值) ├── 参数传递 │ ├── 值传递(默认) │ ├── ref(引用传递,双向) │ └── out(输出参数,单向) ├── 参数特性 │ ├── 默认参数 │ ├── 命名参数 │ └── params(可变参数) ├── 重载:同名不同参 └── 递归:方法调用自身
6.11 练习题
基础题
-
编写一个方法
PrintRectangle(int width, int height),输出由*组成的矩形。 -
编写方法
bool IsEven(int number)判断一个数是否为偶数。 -
编写方法
double CircleArea(double radius)计算圆的面积。 -
编写方法
int Power(int base, int exponent)计算 base 的 exponent 次方(不用 Math.Pow)。
应用题
-
编写方法
int[] GeneratePrimes(int max),返回不超过 max 的所有质数。 -
编写方法
string ReverseString(string input),返回反转
更多推荐
所有评论(0)