第八阶段:方法/函数

QcrTiMo 发布于 9 天前 9 次阅读


前面我们学习了如何存储单个数据(变量)、一组同类型数据(数组),以及如何控制程序的流程(条件语句、循环)。现在,我们要学习一个极为重要的概念,它能帮助我们更好地组织代码、提高代码复用性、让程序结构更清晰,这就是方法 (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); // 错误!无法访问任何方法内部的局部变量
}

学了那么久,是时候自己练习一下了!

现在轮到你来编写方法了!继续在你的项目中练习或者重新创建新的项目:

  1. 创建 PrintUserInfo 方法:
    • 定义一个 private static void PrintUserInfo(string name, int age) 方法。
    • 方法内部打印用户的姓名和年龄,格式类似:"姓名:[name], 年龄:[age] 岁"。
    • 在 Main 方法中调用 PrintUserInfo 两次,传入不同的姓名和年龄。
  2. 创建 GetMax 方法:
    • 定义一个 private static int GetMax(int num1, int num2) 方法。
    • 方法接收两个整数,使用 if-else 判断并返回两者中较大的那个数。
    • 在 Main 方法中调用 GetMax,传入两个数字,并将返回的最大值打印出来。
  3. 创建 CalculateArraySum 方法:
    • 定义一个 private static int CalculateArraySum(int[] numbers) 方法。
    • 方法接收一个 int 数组作为参数。
    • 在方法内部,使用 foreach 或 for 循环计算数组所有元素的和,并返回这个和。
    • 在 Main 方法中:
      • 创建一个 int 数组并初始化一些值。
      • 调用 CalculateArraySum 方法,传入这个数组。
      • 将返回的总和打印出来。
斯哈斯哈斯哈,佳代子啊啊啊啊啊啊ᕕ(◠ڼ◠)ᕗᕕ(◠ڼ◠)ᕗᕕ(◠ڼ◠)ᕗᕕ(◠ڼ◠)ᕗᕕ(◠ڼ◠)ᕗ
最后更新于 2025-05-19