跳转至

方法(函数)#

方法是将一段可复用的代码封装起来的单元。本篇覆盖:方法定义、引用传参(ref / out)、手写字符串方法、递归与重载。方法重载见 方法重载

一、方法的定义#

// 基本语法
[访问修饰符] 返回类型 方法名(参数列表)
{
    // 方法体
    return 返回值;  // 若返回类型为 void,则不需要 return
}
要素 说明
访问修饰符 public / private / internal / protected
返回类型 方法执行完返回的数据类型,无返回值用 void
方法名 遵循 PascalCase 命名规范
参数列表 方法接收的输入,可多个,用逗号分隔

代码组织技巧#

#region 字符串操作
// 使用 #region 折叠代码区域,便于组织代码结构
#endregion

/// <summary>
/// XML 文档注释,用于方法和类前面的说明
/// </summary>

二、引用传参(ref / out)#

1. 回顾:方法参数的赋值#

方法调用时,把实参赋值给形参

参数类型 传递的是什么
值类型实参 保存的是值本身
引用类型实参 保存的是一个地址

2. 方法的传参两种方案#

  • 值传递:形参是实参的一个副本,方法内修改形参不影响实参。
  • 引用传递:使用 refout 关键字,形参和实参指向同一个内存地址,方法内修改会影响实参。

3. ref 关键字#

public static double Dou(double a, double b, ref double c, ref double d)
{
    c = a + b;    // c 被赋值后,外部的 a3 也变了
    d = a / b;    // d 被赋值后,外部的 a4 也变了
    double e = a * b;
    return e;
}

// Main 方法中的调用
double a1 = 8.1, a2 = 2, a3 = 0, a4 = 0;
double b = quote.Dou(a1, a2, ref a3, ref a4);
// 结果:a3 = 10.1(8.1+2),a4 = 4.05(8.1/2),b = 16.2(8.1*2)

特点:

  • ref 传入参数,调用方法时从外部向方法内部传入数据
  • 传入前必须已赋值
public static void RefStu(ref double x, ref double y)
{
    Console.WriteLine($"得到的值是:{x},{y}");
    x = 1231;
    y = 23;
}
// 调用后,外部的 a1 变为 1231,a2 变为 23

4. out 关键字#

public static void OutStu(out double x, out double y)
{
    x = 123;
    y = 123412;
    Console.WriteLine($"得到的值是:{x},{y}");
}

特点:

  • out 传出参数,调用方法时从方法内部向外部传出数据
  • 传入前不用赋值(但不能在传入前取值)
  • 在方法内部必须赋值

5. refout 的区别#

对比项 ref out
传入前是否必须赋值 ✅ 必须赋值 ❌ 不用赋值
方法内部是否必须赋值 ❌ 不是必须 ✅ 必须赋值
主要用途 传入数据(双向) 传出数据(单向输出)

6. 与 return 的对比#

  • return 关键字:方法的返回值,但只能传出一个值。
  • out / ref:可以同时传出多个值。

三、手写字符串方法(作业)#

对应源码:Program.csStuM.cs

1. Contains — 判断字符串是否包含子串#

public static bool Contains(string source, string destination)
{
    if (source.Length < destination.Length) return false;
    if (destination == "") return false;
    for (int i = 0; i <= source.Length - destination.Length; i++)
    {
        string str = "";
        for (int j = i; j < destination.Length + i; j++)
        {
            str += source[j];
        }
        if (str == destination) return true;
    }
    return false;
}

两层循环:外层遍历 source 中每个可能的起始位置,内层从该位置取出与 destination 等长的子串进行比较。

2. StartStr — 判断是否以某子串开头#

// StuM.cs — 存在 bug 的版本
public static bool StartStr(string str1, string str2)
{
    if (str1.Length < str2.Length) return false;
    if (str2 == "") return false;
    string str = "";
    for (int i = 0; i < str2.Length; i++)
    {
        str += str[i];  // ❌ BUG:str 是空字符串,str[i] 会导致索引越界
                        // ✅ 正确写法:str += str1[i];
    }
    if (str2 == str) return true;
    return false;
}

Bug 分析str 是刚初始化的空字符串 ""str[i] 访问的是 str 的第 i 个字符,但 str 长度为 0,所以第一次循环(i=0)就会抛出 IndexOutOfRangeException。应该改为 str1[i] 来取原字符串的字符。

3. EndStr — 判断是否以某子串结尾#

public static bool EndStr(string str1, string str2)
{
    if (str1.Length < str2.Length) return false;
    if (str2 == "") return false;
    for (int i = 0; i <= str1.Length - str2.Length; i++)
    {
        string str3 = "";
        for (int j = i; j < str2.Length - i; j++)
        {
            str3 += str1[j];
        }
        if (str3 == str2 && str1[str1.Length - str2.Length] == str2[0])
        {
            return true;
        }
    }
    return false;
}

4. StuM.cs 字符串方法中的 Bug 汇总#

方法名 所在文件 问题代码 正确写法 后果
StartStr StuM.cs 第68行 str += str[i] str += str1[i] 空字符串越界,运行时崩溃
EndtStr StuM.cs 第92行 str += str[i] str += str1[i] 空字符串越界,运行时崩溃

两个方法犯的是同一个错误:把局部变量 str(用于拼接结果的空字符串)误写成了索引来源,应该访问的是参数 str1

5. Concat — 拼接字符串数组#

public static string Concat(string[] str00)
{
    string str = "";
    for (int i = 0; i < str00.Length; i++)
    {
        str += str00[i];
    }
    return str;
}

6. NineTable — 生成乘法表#

public static string NineTable(int num)
{
    string n = "";
    for (int i = 1; i <= num; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            n += $"{j}×{i}={j * i}\t";
        }
        n += "\n";
    }
    return n;
}

生成指定行数的乘法表(下三角格式),例如 NineTable(9) 输出完整的九九乘法表。

四、Main 方法调用示例#

static void Main(string[] args)
{
    string[] str2 = { "123", "1wer", "1639812639" };

    // 字符串操作
    Console.WriteLine(Contains("12314", "12"));   // true
    Console.WriteLine(EndStr("12314", "1"));      // 判断是否以 "1" 结尾
    Console.WriteLine(Concat(str2));              // "1231wer1639812639"

    // 引用传参
    double a1 = 8.1, a2 = 2, a3 = 0, a4 = 0;
    double b = quote.Dou(a1, a2, ref a3, ref a4);
    Console.WriteLine($"{a3},{a4},{b}");           // 10.1, 4.05, 16.2

    StuOut.RefStu(ref a1, ref a2);
    Console.WriteLine($"最后得到{a1},{a2}");        // 最后得到1231,23
}

五、关键知识点总结#

知识点 说明
ref 引用传参,传入前必须赋值,方法内可读写
out 引用传参,传入前不用赋值,方法内必须赋值
return 返回值,只能返回一个值
Contains 手写字符串包含判断,双层循环遍历
StartStr 判断字符串是否以某子串开头
EndStr 判断字符串是否以某子串结尾
Concat 拼接字符串数组
NineTable 生成九九乘法表
#region 代码折叠区域,便于组织代码结构
/// <summary> XML 文档注释,用于方法和类前面的说明
StuM.cs Bug StartStrEndtStrstr[i] 应改为 str1[i],否则空字符串越界崩溃

相关笔记#