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. 方法的性能优化建议
- 方法体不要太大,单一职责,便于测试和维护。
- 局部变量优先用栈内存,减少堆分配。
- 方法参数尽量用值类型,引用类型要注意副作用。
- 对于频繁调用的方法,可以用内联(编译器自动优化)。

2921

被折叠的 条评论
为什么被折叠?



