C#方法详解

1. 什么是方法

方法(Method) 是一组用于执行特定任务的代码块,可以带参数和返回值。方法可以提高代码的复用性和可维护性。


2. 方法的基本结构

[修饰符] 返回类型 方法名([参数列表])
{
    // 方法体
    [return 返回值;]
}

示例:

public int Add(int a, int b)
{
    return a + b;
}

3. 方法的调用

int result = Add(3, 5); // 调用Add方法,传入参数3和5

4. 方法的参数

4.1 普通参数

void Print(string message)
{
    Console.WriteLine(message);
}

4.2 默认参数

void Greet(string name = "Guest")
{
    Console.WriteLine("Hello, " + name);
}

4.3 params参数(可变参数)

void Sum(params int[] numbers)
{
    int total = 0;
    foreach (int num in numbers)
        total += num;
    Console.WriteLine(total);
}

4.4 ref和out参数

  • ref:传递引用,要求参数必须初始化。
  • out:输出参数,调用前不要求初始化,方法内必须赋值。
void Double(ref int x)
{
    x *= 2;
}

void GetValues(out int a, out int b)
{
    a = 1;
    b = 2;
}

5. 返回值

  • 如果没有返回值,使用 void
  • 有返回值,方法体内必须用 return 返回对应类型的值。
string GetName()
{
    return "Tom";
}

6. 方法重载

方法名相同,参数类型或数量不同。

void Show(string msg) { }
void Show(int num) { }

7. 访问修饰符

  • public:公有,任何地方都可访问。
  • private:私有,只有类内部可访问。
  • protected:受保护,派生类可访问。
  • internal:同程序集可访问。

8. 静态方法与实例方法

  • 静态方法:属于类,不属于对象。用类名调用。
  • 实例方法:属于对象,需创建对象后调用。
class MathUtil
{
    public static int Add(int a, int b) { return a + b; }
    public int Multiply(int a, int b) { return a * b; }
}

// 静态方法调用
int sum = MathUtil.Add(2, 3);

// 实例方法调用
MathUtil util = new MathUtil();
int product = util.Multiply(2, 3);

9. 方法的注释与文档

/// <summary>
/// 计算两个整数的和
/// </summary>
public int Add(int a, int b)
{
    return a + b;
}

10. 综合示例

class Program
{
    // 静态方法
    public static int Add(int x, int y)
    {
        return x + y;
    }

    // 实例方法
    public void SayHello(string name)
    {
        Console.WriteLine("Hello, " + name);
    }

    // 重载
    public void Show(int num)
    {
        Console.WriteLine(num);
    }
    public void Show(string str)
    {
        Console.WriteLine(str);
    }

    static void Main(string[] args)
    {
        int sum = Add(3, 5); // 静态方法
        Program p = new Program();
        p.SayHello("Alice"); // 实例方法
        p.Show(123);         // 方法重载
        p.Show("abc");
    }
}

11. 泛型方法

泛型方法可以让方法在不同类型下复用,提高代码灵活性。


public T Max<T>(T a, T b) where T : IComparable<T>
{
    return a.CompareTo(b) > 0 ? a : b;
}

// 调用
int maxInt = Max(3, 7);
string maxStr = Max("apple", "banana");

12. 递归方法

方法可以自己调用自己,称为递归。常用于数学计算等场景。

public int Factorial(int n)
{
    if (n <= 1)
        return 1;
    return n * Factorial(n - 1);
}

**注意:**递归要有终止条件,否则会导致栈溢出。


13. 匿名方法与 Lambda 表达式

匿名方法

匿名方法没有名字,常用在委托中。

Action<string> print = delegate(string msg)
{
    Console.WriteLine(msg);
};

print("Hello, World!");

Lambda 表达式

Lambda 表达式是匿名方法的简化写法。

Action<string> print = msg => Console.WriteLine(msg);
print("Hello, Lambda!");

14. 扩展方法

扩展方法让你为已有类型添加新方法,而不需要修改源代码。

public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string str)
    {
        return string.IsNullOrEmpty(str);
    }
}

// 使用扩展方法
string s = "";
bool result = s.IsNullOrEmpty();

15. 局部函数(Local Function)

C# 7.0 起支持在方法内部定义局部函数,用于简化逻辑、提高代码可读性。

public void Process()
{
    int Add(int a, int b) => a + b;
    Console.WriteLine(Add(1, 2));
}

16. 方法生命周期和作用域

  • 方法定义在类、结构体或接口内。
  • 方法内部定义的变量为局部变量,只在方法体内有效。
  • 方法参数也是局部变量,离开方法后即被销毁。

17. 异步方法(async/await)

C# 支持异步方法,提升程序性能,避免阻塞主线程。

public async Task<int> GetDataAsync()
{
    await Task.Delay(1000); // 模拟异步操作
    return 42;
}

// 调用
int result = await GetDataAsync();

18. 方法最佳实践

  • 方法名要见名知意,遵循驼峰命名法。
  • 方法长度不宜过长,建议单一职责。
  • 合理使用参数,避免参数过多。
  • 对于公共方法加上 XML 注释,便于维护和自动生成文档。
  • 合理选择方法的访问修饰符(如 public、private、protected)。
  • 对于可能抛异常的方法,使用 try-catch 处理异常。

19. 常见错误

  • 返回类型与 return 值不匹配。
  • 方法重载时参数类型或数量完全相同,编译器无法区分。
  • 忘记给方法加返回值或 return 语句。
  • 静态方法中访问实例成员,或实例方法中访问静态成员时出错。
  • 参数未初始化就用 ref 调用。

20. 其他补充

方法的委托

方法可以赋值给委托类型,实现回调等功能。

public delegate int Calculate(int x, int y);

public int Add(int x, int y) => x + y;

Calculate calc = Add;
int result = calc(2, 3); // 结果为5

方法的参数命名与命名参数调用

public void PrintInfo(string name, int age)
{
    Console.WriteLine($"{name}, {age}");
}

PrintInfo(age: 20, name: "Tom"); // 可以指定参数名,顺序可

21. 方法与事件

在 C# 中,方法常用于事件的响应(事件处理器)。事件本质上是委托的一种特殊应用。

public class Button
{
    public event Action Click;

    public void OnClick()
    {
        Click?.Invoke();
    }
}

class Program
{
    static void Main()
    {
        Button btn = new Button();
        btn.Click += Btn_Click; // 订阅事件
        btn.OnClick();          // 触发事件
    }

    static void Btn_Click()
    {
        Console.WriteLine("按钮被点击了!");
    }
}

22. 方法的可选参数与命名参数

在方法声明时,可以为参数设置默认值,实现可选参数。在调用时,可以使用命名参数。

void Show(string msg, int count = 1)
{
    for (int i = 0; i < count; i++)
        Console.WriteLine(msg);
}

Show("Hello");          // count 默认 1
Show("Hi", 3);          // count = 3
Show(count: 2, msg: "Hey"); // 使用命名参数

23. 方法的递归与尾递归优化

递归方法容易导致栈溢出,C# 编译器对尾递归有一定优化,但实际应用中建议用循环替代深度递归。

普通递归:

int Fib(int n)
{
    if (n <= 2) return 1;
    return Fib(n - 1) + Fib(n - 2);
}

用循环优化:

int FibLoop(int n)
{
    int a = 1, b = 1;
    for (int i = 3; i <= n; i++)
    {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

24. 方法的参数传递方式

  • 值传递:默认方式,传递的是参数的副本,方法内修改不影响外部变量。
  • 引用传递:通过 ref 或 out,方法内修改会影响外部变量。
  • 参数数组params 修饰符,允许传入任意数量参数。

25. 方法的访问级别与封装

  • private:只在类内部可见,常用于辅助性方法。
  • protected:子类可见,常用于继承和多态。
  • internal:同程序集可见,适用于组件级开发。
  • public:任何地方可见,适用于 API、库开发。

26. 方法的多态性(虚方法与重写)

通过 virtual 和 override,实现方法的多态性。


class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("动物叫声");
    }
}

class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("汪汪!");
    }
}

Animal a = new Dog();
a.Speak(); // 输出:汪汪!

27. 方法的抽象(abstract)

抽象方法没有实现,必须在派生类中重写。

abstract class Shape
{
    public abstract double Area();
}

class Circle : Shape
{
    public double Radius { get; set; }
    public override double Area()
    {
        return Math.PI * Radius * Radius;
    }
}

28. 方法的接口实现

接口中的方法没有实现,类必须实现接口的方法。

interface IPrinter
{
    void Print(string content);
}

class ConsolePrinter : IPrinter
{
    public void Print(string content)
    {
        Console.WriteLine(content);
    }
}

29. 方法的异常处理

方法内部可以处理异常,保证程序健壮性。

public int Divide(int a, int b)
{
    try
    {
        return a / b;
    }
    catch (DivideByZeroException)
    {
        Console.WriteLine("除数不能为零!");
        return 0;
    }
}

30. 方法的文档注释与智能提示

使用三斜杠 /// 注释,可以自动生成 API 文档和智能提示。

/// <summary>
/// 计算两个整数的和
/// </summary>
/// <param name="a">第一个数</param>
/// <param name="b">第二个数</param>
/// <returns>和</returns>
public int Add(int a, int b)
{
    return a + b;
}

31. 方法的调用栈与调试

每次方法调用,都会在调用栈压入一帧。可以用调试工具(如 Visual Studio)逐步跟踪方法调用,查看参数和返回值。


32. 方法的性能优化建议

  • 方法体不要太大,单一职责,便于测试和维护。
  • 局部变量优先用栈内存,减少堆分配。
  • 方法参数尽量用值类型,引用类型要注意副作用。
  • 对于频繁调用的方法,可以用内联(编译器自动优化)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猩火燎猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值