C Sharp 异常处理策略
外观
C#异常处理策略[编辑 | 编辑源代码]
异常处理是C#编程中确保程序健壮性和可靠性的核心机制。本指南将系统讲解C#异常处理的最佳实践,涵盖基础概念到高级策略,并提供实际应用案例。
1. 异常处理基础[编辑 | 编辑源代码]
异常(Exception)是程序运行时发生的意外情况,可能由以下原因导致:
- 无效的用户输入
- 文件/网络资源不可用
- 内存不足
- 编程逻辑错误
C#使用try-catch-finally结构处理异常:
try {
// 可能抛出异常的代码
int.Parse("abc"); // 格式错误
}
catch (FormatException ex) {
Console.WriteLine($"输入格式错误: {ex.Message}");
}
finally {
Console.WriteLine("清理资源执行区");
}
输出:
输入格式错误: Input string was not in a correct format. 清理资源执行区
2. 异常类型层次[编辑 | 编辑源代码]
关键异常类型:
- System.Exception:所有异常的基类
- System.SystemException:CLR抛出的系统级异常
- System.ApplicationException:用户自定义异常的基类(不推荐继承)
3. 最佳实践策略[编辑 | 编辑源代码]
3.1 精确捕获异常[编辑 | 编辑源代码]
避免捕获基类Exception,应捕获具体异常类型:
// 不推荐
try { /* 代码 */ }
catch (Exception ex) { /* 处理所有异常 */ }
// 推荐做法
try {
File.ReadAllText("missing.txt");
}
catch (FileNotFoundException ex) {
Console.WriteLine("文件未找到,请检查路径");
}
catch (IOException ex) {
Console.WriteLine("IO错误: " + ex.Message);
}
3.2 异常筛选器(C# 6+)[编辑 | 编辑源代码]
使用when关键字添加条件判断:
try {
ConnectToDatabase();
}
catch (SqlException ex) when (ex.Number == 1205) {
// 处理死锁特定错误
RetryOperation();
}
catch (SqlException ex) {
LogError(ex);
throw; // 重新抛出
}
3.3 资源清理模式[编辑 | 编辑源代码]
使用using语句自动释放IDisposable资源:
using (var stream = new FileStream("data.txt", FileMode.Open))
{
// 使用stream对象
} // 自动调用Dispose()
等效于:
FileStream stream = null;
try {
stream = new FileStream("data.txt", FileMode.Open);
// 使用stream
}
finally {
stream?.Dispose();
}
4. 自定义异常[编辑 | 编辑源代码]
创建自定义异常应继承自Exception类:
public class InventoryException : Exception
{
public int ItemId { get; }
public InventoryException(int itemId, string message)
: base(message) => ItemId = itemId;
}
// 使用示例
try {
if (stockCount <= 0)
throw new InventoryException(123, "库存不足");
}
catch (InventoryException ex) {
Console.WriteLine($"商品{ex.ItemId}异常: {ex.Message}");
}
5. 性能考量[编辑 | 编辑源代码]
异常处理开销较大,应避免:
- 使用异常控制正常流程
- 在频繁调用的代码中捕获异常
优化方案:
// 使用Try模式替代异常
if (int.TryParse(input, out var number)) {
// 成功处理
}
else {
// 处理无效输入
}
6. 实际案例:Web API异常处理[编辑 | 编辑源代码]
ASP.NET Core中的全局异常处理:
// 自定义异常中间件
public class ExceptionMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try {
await next(context);
}
catch (ValidationException ex) {
context.Response.StatusCode = 400;
await context.Response.WriteAsJsonAsync(new {
Error = "验证失败",
Details = ex.Errors
});
}
catch (Exception ex) {
// 记录日志
Log.Error(ex, "全局异常");
context.Response.StatusCode = 500;
await context.Response.WriteAsJsonAsync(new {
Error = "系统错误",
RequestId = context.TraceIdentifier
});
}
}
}
7. 异常处理数学建模[编辑 | 编辑源代码]
异常处理概率模型: 其中:
- :第i类异常发生概率
- :对该异常的成功处理概率
总结[编辑 | 编辑源代码]
场景 | 推荐做法 | 避免做法 |
---|---|---|
using语句/Dispose模式 | 依赖finalizer | ||
Try模式(如TryParse) | 使用异常控制流程 | ||
记录日志后终止 | 静默吞没异常 | ||
包装自定义异常 | 暴露底层异常细节 |
遵循这些策略可显著提高代码的健壮性和可维护性。记住:异常处理的目标不是消除所有异常,而是确保程序在异常情况下能优雅降级或安全终止。