前面我们学习了如何存储单个数据(变量)、一组同类型数据(数组),以及如何控制程序的流程(条件语句、循环)。现在,我们要学习一个极为重要的概念,它能帮助我们更好地组织代码、提高代码复用性、让程序结构更清晰,这就是方法 (Methods)(在其他一些编程语言里也叫函数 Functions)。
什么是方法?为什么要使用方法?
想象一下,你想在游戏脚本写NPC的属性,但是NPC又有许多种,重复编写NPC的底层代码实在是太多太麻烦了。更好的办法就是写一个函数,在写拥有其它函数的NPC时,你可以引用这个小函数,而不需要重复编写代码。
方法就扮演着类似函数的角色。它是一段包含了一系列执行特定任务的语句的代码块,并且有一个名字。你可以通过这个名字随时调用它来执行这些语句。
使用方法的好处:
- 代码重用: 如果一段逻辑需要在程序的不同地方多次使用(比如,打印一条分隔线、计算两个数的和),你只需要把这段逻辑写在一个方法里,然后在需要的地方调用这个方法即可,避免了复制代码。遵循 DRY (Don't Repeat Yourself) 原则。
- 代码组织: 将大的、复杂的程序分解成一个个小的、功能明确的方法,使得程序结构更清晰,更容易理解。
- 可读性: 有意义的方法名可以清楚地表明这段代码的功能,让其他人(或者未来的你)更容易读懂代码。
- 可维护性: 当你需要修改某个功能时,只需要找到并修改对应的方法即可,而不需要在整个程序中到处寻找和修改重复的代码。
- 抽象: 方法的使用者只需要知道方法是做什么的(通过方法名和参数),而不需要关心它是如何做的(内部实现细节)。
定义一个方法
在 C# 中,我们通常在类 (Class) 的内部定义方法。目前我们主要在 Program 类中编写代码。为了方便在 Main 方法(程序的入口)中直接调用,我们通常将自己定义的方法也声明为 static。
让我们先恢复一下带有 Main 方法的标准 Program 类结构,这样更方便我们定义其他 static 方法:
using System;
// 定义一个类 Program
internal class Program
{
// 程序的主入口方法
static void Main(string[] args)
{
// 我们将在这里调用我们自己定义的方法
Console.WriteLine("程序开始执行...");
// 调用我们下面定义的 SayHello 方法
SayHello();
Console.WriteLine("调用 SayHello 结束。");
// 调用我们下面定义的 PrintSeparator 方法
PrintSeparator();
Console.WriteLine("程序执行完毕。");
Console.ReadKey(); // 暂停看结果
}
// --- 在这里定义我们自己的方法 ---
// 定义一个简单的方法,不接收参数,也不返回值 (void)
// private: 表示这个方法只能在 Program 类内部被访问
// static: 表示这个方法属于 Program 类本身,而不是类的实例
// void: 表示这个方法不返回任何值
// SayHello: 方法名
// (): 表示这个方法不需要参数
private static void SayHello()
{
Console.WriteLine("--------------------");
Console.WriteLine("Hello from the method!");
Console.WriteLine("欢迎学习 C# 方法!");
Console.WriteLine("--------------------");
}
// 定义另一个简单的方法,用于打印分隔线
private static void PrintSeparator()
{
Console.WriteLine("====================");
}
} // class Program 结束
方法定义语法详解:
[访问修饰符] static [返回类型] [方法名]([参数列表])
{
// 方法体:包含具体的代码逻辑
}
- [访问修饰符]: 控制方法的可见性(谁可以调用这个方法)。
- public: 任何地方都可以访问。
- private: 只能在定义它的类内部访问 (我们例子中用的就是 private)。
- 还有 internal, protected 等,我们后面再学。暂时用 private 就好。
- 如果省略,默认为 private。
- static: 这个关键字表示该方法是静态方法。静态方法属于类本身,而不是类的某个具体实例(对象)。因为我们的 Main 方法是 static 的,所以为了在 Main 中直接调用其他方法,这些方法通常也需要是 static 的。(面向对象编程时会学习非静态方法)。
- [返回类型] : 指定方法执行完毕后返回的数据类型。
- void: 如果方法不返回任何值,就使用 void。像 SayHello 和 PrintSeparator 只是执行一些操作(打印),不产生需要返回的结果。
- 其他数据类型: 如果方法需要返回一个计算结果,比如 int, string, bool, double,甚至是数组 int[] 或自定义类对象,就需要在这里指定对应的类型。
- [方法名] : 给方法起的名字。
- 命名规范: 使用 PascalCase 命名法(每个单词首字母大写),例如 CalculateSum, GetUserName。
- 名字应该清晰地描述该方法的功能,通常是动词或动词短语。
- ([参数列表]) : 定义方法运行时需要接收的输入数据。
- 参数是定义在方法名后面的圆括号 () 里的。
- 如果没有参数,括号 () 也必须保留,里面为空。
- 如果有一个或多个参数,格式为 dataType parameterName,多个参数之间用逗号 , 分隔。例如 (int number1, int number2),(string name, int age)。
- dataType 是参数的数据类型。
- parameterName 是参数的名称(在方法体内部使用,遵循 camelCase 命名法)。
- { // 方法体 } : 包含在大括号 {} 里的代码块,是方法实际执行的逻辑。
调用方法
定义好方法后,就可以在程序的其他地方(比如 Main 方法或其他方法内部)通过方法名来调用它了。
基本语法:
MethodName([arguments]);
/*MethodName: 要调用的方法的名称。
[arguments]: 传递给方法的实际值,称为参数 (Arguments)。
如果方法定义时没有参数,调用时括号 () 也是空的。
如果方法定义时有参数,调用时需要按照顺序提供对应类型的值或变量。传递的实际值就叫做参数 (Arguments)。
参数的数量、类型和顺序必须与方法定义中的参数列表匹配。*/
代码示例(调用上面定义的 SayHello 和 PrintSeparator):
在 Main 方法中,我们已经写了:
SayHello(); // 调用 SayHello 方法
PrintSeparator(); // 调用 PrintSeparator 方法
方法参数(Parameters vs. Arguments)
- 方法参数 (Parameters): 定义在方法签名(方法头)的括号里的变量,它们是方法接收输入的占位符。比如 void PrintMessage(string message) 中的 message 就是一个参数。
- 调用参数 (Arguments): 在调用方法时,传递给方法的实际值。比如 PrintMessage("你好!"); 中的 "你好!" 就是一个参数。
代码示例:
// 定义一个带 string 参数的方法
private static void GreetUser(string name) // name 是参数 (parameter)
{
Console.WriteLine($"你好, {name}! 欢迎使用本程序。");
}
// 在 Main 方法中调用
static void Main(string[] args)
{
// ... 其他代码 ...
GreetUser("张三"); // "张三" 是参数 (argument)
GreetUser("李四"); // "李四" 是参数 (argument)
string userName = "王五";
GreetUser(userName); // userName 变量的值 ("王五") 作为参数 (argument)
// ... 其他代码 ...
}
返回值 (return 关键字)
如果方法的返回类型不是 void,那么它必须使用 return 关键字返回一个与声明的返回类型相匹配的值。
- return 语句会立即结束当前方法的执行,并将指定的值返回给调用者。
- 一个方法可以有多个 return 语句(例如在 if-else 分支中),但只有一条会被执行。
- void 方法也可以使用 return;(不带值)来提前结束执行,但不常用。
代码示例 (带返回值的方法):
// 定义一个计算两个整数和的方法,返回 int 类型
private static int AddNumbers(int num1, int num2)
{
int sum = num1 + num2;
return sum; // 返回计算结果
// Console.WriteLine("这行代码永远不会执行,因为 return 已经结束了方法");
}
// 定义一个判断是否成年人的方法,返回 bool 类型
private static bool IsAdult(int age)
{
if (age >= 18)
{
return true; // 满足条件,返回 true 并结束方法
}
else
{
return false; // 不满足条件,返回 false 并结束方法
}
// 也可以简化为: return age >= 18;
}
// 在 Main 方法中调用并使用返回值
static void Main(string[] args)
{
// ... 其他代码 ...
// 调用 AddNumbers 并接收返回值
int result = AddNumbers(10, 5); // 调用方法,将返回值 15 赋给 result 变量
Console.WriteLine($"10 + 5 = {result}");
int calculation = AddNumbers(result, 3); // 可以用变量作为参数
Console.WriteLine($"之前的和再加上 3 是:{calculation}"); // 输出 18
PrintSeparator();
// 调用 IsAdult 并使用返回值
int myAge = 25;
bool canVote = IsAdult(myAge); // canVote 会是 true
if (canVote)
{
Console.WriteLine($"{myAge} 岁,是成年人,可以投票。");
}
else
{
Console.WriteLine($"{myAge} 岁,不是成年人。");
}
if (IsAdult(16)) // 直接在 if 条件中使用返回值 (false)
{
Console.WriteLine("16 岁是成年人。"); // 这行不会执行
}
else
{
Console.WriteLine("16 岁不是成年人。"); // 这行会执行
}
// ... 其他代码 ...
}
方法中的变量作用域
在方法内部声明的变量(包括参数)称为局部变量。它们的作用域仅限于该方法内部。
- 局部变量在方法开始执行时创建(或进入其声明的代码块时)。
- 方法执行结束后,局部变量就会被销毁,其占用的内存会被回收。
- 你不能在方法外部访问该方法内部的局部变量。
- 不同方法中可以有同名的局部变量,它们是完全独立的。
代码示例:
private static void MethodA()
{
int localVarA = 100; // localVarA 是 MethodA 的局部变量
Console.WriteLine($"在 MethodA 中, localVarA = {localVarA}");
// Console.WriteLine(localVarB); // 错误!无法访问 MethodB 的局部变量
}
private static void MethodB()
{
int localVarB = 200; // localVarB 是 MethodB 的局部变量
int localVarA = 50; // 这与 MethodA 中的 localVarA 是不同的变量
Console.WriteLine($"在 MethodB 中, localVarB = {localVarB}");
Console.WriteLine($"在 MethodB 中, localVarA = {localVarA}"); // 输出 50
// Console.WriteLine(localVarA from MethodA); // 错误!无法访问
}
static void Main(string[] args)
{
MethodA();
MethodB();
// Console.WriteLine(localVarA); // 错误!无法访问任何方法内部的局部变量
}
学了那么久,是时候自己练习一下了!
现在轮到你来编写方法了!继续在你的项目中练习或者重新创建新的项目:
- 创建 PrintUserInfo 方法:
- 定义一个 private static void PrintUserInfo(string name, int age) 方法。
- 方法内部打印用户的姓名和年龄,格式类似:"姓名:[name], 年龄:[age] 岁"。
- 在 Main 方法中调用 PrintUserInfo 两次,传入不同的姓名和年龄。
- 创建 GetMax 方法:
- 定义一个 private static int GetMax(int num1, int num2) 方法。
- 方法接收两个整数,使用 if-else 判断并返回两者中较大的那个数。
- 在 Main 方法中调用 GetMax,传入两个数字,并将返回的最大值打印出来。
- 创建 CalculateArraySum 方法:
- 定义一个 private static int CalculateArraySum(int[] numbers) 方法。
- 方法接收一个 int 数组作为参数。
- 在方法内部,使用 foreach 或 for 循环计算数组所有元素的和,并返回这个和。
- 在 Main 方法中:
- 创建一个 int 数组并初始化一些值。
- 调用 CalculateArraySum 方法,传入这个数组。
- 将返回的总和打印出来。
Comments NOTHING