异常处理概述 #
一、异常概述 #
异常是程序运行时发生的错误,C#通过异常处理机制来捕获和处理这些错误。
1.1 异常特点 #
- 打断正常程序流程
- 包含错误信息
- 可以被捕获和处理
- 沿调用栈传播
1.2 异常处理的好处 #
- 分离正常逻辑和错误处理
- 统一的错误处理机制
- 丰富的错误信息
- 强制处理错误
二、异常类层次结构 #
2.1 基本结构 #
text
System.Object
└── System.Exception
├── System.SystemException
│ ├── ArgumentException
│ ├── ArgumentNullException
│ ├── ArgumentOutOfRangeException
│ ├── ArithmeticException
│ │ ├── DivideByZeroException
│ │ ├── OverflowException
│ │ └── NotFiniteNumberException
│ ├── FormatException
│ ├── IndexOutOfRangeException
│ ├── InvalidOperationException
│ ├── NullReferenceException
│ ├── OutOfMemoryException
│ └── StackOverflowException
├── ApplicationException
├── IOException
│ ├── FileNotFoundException
│ ├── DirectoryNotFoundException
│ └── EndOfStreamException
└── UnauthorizedAccessException
2.2 Exception类属性 #
csharp
public class Exception
{
public virtual string Message { get; }
public virtual string StackTrace { get; }
public Exception InnerException { get; }
public string Source { get; set; }
public MethodBase TargetSite { get; }
public string HelpLink { get; set; }
public IDictionary Data { get; }
}
2.3 获取异常信息 #
csharp
try
{
int result = 10 / 0;
}
catch (Exception ex)
{
Console.WriteLine($"消息:{ex.Message}");
Console.WriteLine($"类型:{ex.GetType().Name}");
Console.WriteLine($"堆栈:{ex.StackTrace}");
Console.WriteLine($"来源:{ex.Source}");
}
三、异常分类 #
3.1 系统异常 #
由CLR抛出的异常:
| 异常 | 说明 |
|---|---|
| NullReferenceException | 空引用异常 |
| IndexOutOfRangeException | 索引越界 |
| DivideByZeroException | 除零异常 |
| OverflowException | 溢出异常 |
| OutOfMemoryException | 内存不足 |
| StackOverflowException | 栈溢出 |
csharp
string s = null;
Console.WriteLine(s.Length);
int[] arr = new int[5];
Console.WriteLine(arr[10]);
int x = 10, y = 0;
int result = x / y;
checked
{
int max = int.MaxValue + 1;
}
3.2 应用程序异常 #
由应用程序抛出的异常:
| 异常 | 说明 |
|---|---|
| ArgumentException | 参数异常 |
| ArgumentNullException | 参数为空 |
| ArgumentOutOfRangeException | 参数超出范围 |
| FormatException | 格式错误 |
| InvalidOperationException | 无效操作 |
csharp
public void SetAge(int age)
{
if (age < 0)
throw new ArgumentOutOfRangeException(nameof(age), "年龄不能为负数");
if (age > 150)
throw new ArgumentOutOfRangeException(nameof(age), "年龄超出合理范围");
}
public void Process(string data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));
if (string.IsNullOrWhiteSpace(data))
throw new ArgumentException("数据不能为空", nameof(data));
}
3.3 I/O异常 #
文件和输入输出相关异常:
| 异常 | 说明 |
|---|---|
| IOException | I/O操作异常 |
| FileNotFoundException | 文件未找到 |
| DirectoryNotFoundException | 目录未找到 |
| PathTooLongException | 路径过长 |
| UnauthorizedAccessException | 访问被拒绝 |
csharp
try
{
string content = File.ReadAllText("nonexistent.txt");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"文件未找到:{ex.FileName}");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("没有访问权限");
}
catch (IOException ex)
{
Console.WriteLine($"I/O错误:{ex.Message}");
}
四、常见异常场景 #
4.1 空引用异常 #
csharp
string name = null;
if (name != null)
{
Console.WriteLine(name.Length);
}
Console.WriteLine(name?.Length ?? 0);
4.2 类型转换异常 #
csharp
object obj = "Hello";
if (obj is int number)
{
Console.WriteLine(number);
}
if (int.TryParse("123", out int result))
{
Console.WriteLine(result);
}
4.3 集合操作异常 #
csharp
var list = new List<int>();
if (list.Count > 0)
{
var first = list[0];
}
var firstOrDefault = list.FirstOrDefault();
var dict = new Dictionary<string, int>();
if (dict.TryGetValue("key", out int value))
{
Console.WriteLine(value);
}
4.4 文件操作异常 #
csharp
string path = "test.txt";
if (File.Exists(path))
{
string content = File.ReadAllText(path);
}
try
{
using var stream = File.OpenRead(path);
}
catch (FileNotFoundException)
{
Console.WriteLine("文件不存在");
}
五、异常传播 #
5.1 调用栈传播 #
csharp
public void MethodA()
{
MethodB();
}
public void MethodB()
{
MethodC();
}
public void MethodC()
{
throw new Exception("MethodC中的异常");
}
5.2 内部异常 #
csharp
public void LoadConfig(string path)
{
try
{
string content = File.ReadAllText(path);
ParseConfig(content);
}
catch (Exception ex)
{
throw new ConfigurationException("配置加载失败", ex);
}
}
public class ConfigurationException : Exception
{
public ConfigurationException(string message, Exception innerException)
: base(message, innerException)
{
}
}
六、异常最佳实践 #
6.1 避免使用异常控制流程 #
csharp
if (int.TryParse(input, out int number))
{
Process(number);
}
else
{
Console.WriteLine("输入无效");
}
try
{
int number = int.Parse(input);
Process(number);
}
catch (FormatException)
{
Console.WriteLine("输入无效");
}
6.2 抛出有意义的异常 #
csharp
public void Withdraw(decimal amount)
{
if (amount <= 0)
throw new ArgumentException("取款金额必须大于0", nameof(amount));
if (amount > _balance)
throw new InvalidOperationException("余额不足");
_balance -= amount;
}
6.3 使用特定异常类型 #
csharp
public void Process(string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (value.Length == 0)
throw new ArgumentException("值不能为空字符串", nameof(value));
if (value.Length > 100)
throw new ArgumentOutOfRangeException(nameof(value), "值长度不能超过100");
}
七、总结 #
异常处理要点:
| 要点 | 说明 |
|---|---|
| Exception | 所有异常的基类 |
| SystemException | 系统异常 |
| ApplicationException | 应用异常 |
| IOException | I/O异常 |
| Message | 异常消息 |
| StackTrace | 调用堆栈 |
下一步,让我们学习try-catch语句!
最后更新:2026-03-26