异常是程序执行过程中发生的错误或异常情况,它中断了正常的程序流程。C#使用异常机制来处理错误情况。
System.Object
System.Exception
System.SystemException
System.ArithmeticException
System.DivideByZeroException
System.OverflowException
System.ArgumentException
System.ArgumentNullException
System.ArgumentOutOfRangeException
System.IndexOutOfRangeException
System.InvalidOperationException
System.NullReferenceException
System.StackOverflowException
System.ApplicationException
try { // 可能抛出异常的代码 int result = 10 / 0; // 会抛出DivideByZeroException } catch (DivideByZeroException ex) { // 处理特定异常 Console.WriteLine($"除零错误: {ex.Message}"); } catch (Exception ex) { // 处理所有其他异常 Console.WriteLine($"错误: {ex.Message}"); } finally { // 无论是否发生异常都会执行 Console.WriteLine("清理资源"); }
public void ProcessFile(string path) { try { string content = File.ReadAllText(path); int number = int.Parse(content); Console.WriteLine(number * 2); } catch (FileNotFoundException ex) { Console.WriteLine($"文件未找到: {ex.FileName}"); } catch (FormatException ex) { Console.WriteLine("文件内容格式错误"); } catch (IOException ex) { Console.WriteLine($"IO错误: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"未知错误: {ex.Message}"); } }
public void ReadFile(string path) { StreamReader reader = null; try { reader = new StreamReader(path); string content = reader.ReadToEnd(); Console.WriteLine(content); } catch (FileNotFoundException) { Console.WriteLine("文件不存在"); } finally { // 确保资源被释放 reader?.Close(); Console.WriteLine("文件读取完成"); } } // 更好的方式 - using语句 public void ReadFileBetter(string path) { try { using (var reader = new StreamReader(path)) { string content = reader.ReadToEnd(); Console.WriteLine(content); } // 自动调用Dispose } catch (FileNotFoundException) { Console.WriteLine("文件不存在"); } }
public void Withdraw(decimal amount) { if (amount < 0) { throw new ArgumentException("取款金额不能为负数", nameof(amount)); } if (amount > Balance) { throw new InvalidOperationException("余额不足"); } Balance -= amount; }
try { ProcessData(); } catch (Exception ex) { // 方式1:保留原始堆栈信息 throw; // 方式2:丢失原始堆栈 // throw ex; // 方式3:包装异常 // throw new ApplicationException("处理数据失败", ex); }
// 业务异常基类 public class BusinessException : Exception { public string ErrorCode { get; } public DateTime Timestamp { get; } public BusinessException(string message, string errorCode) : base(message) { ErrorCode = errorCode; Timestamp = DateTime.Now; } public BusinessException(string message, string errorCode, Exception innerException) : base(message, innerException) { ErrorCode = errorCode; Timestamp = DateTime.Now; } } // 具体的业务异常 public class InsufficientFundsException : BusinessException { public decimal RequestedAmount { get; } public decimal AvailableBalance { get; } public InsufficientFundsException(decimal requested, decimal available) : base($"余额不足。请求: {requested:C}, 可用: {available:C}", "ERR_INSUFFICIENT_FUNDS") { RequestedAmount = requested; AvailableBalance = available; } } public class InvalidTransferException : BusinessException { public string AccountNumber { get; } public InvalidTransferException(string accountNumber, string reason) : base($"转账失败: {reason}", "ERR_INVALID_TRANSFER") { AccountNumber = accountNumber; } }
// 1. 捕获特定的异常 public void GoodPractice1() { try { int.Parse("abc"); } catch (FormatException ex) // 好的做法 { Console.WriteLine("格式错误"); } } // 2. 使用finally或using清理资源 public void GoodPractice2() { using var stream = new FileStream("data.txt", FileMode.Open); // 处理文件 } // 3. 提供有意义的错误信息 public void GoodPractice3(string userName) { if (string.IsNullOrWhiteSpace(userName)) { throw new ArgumentException("用户名不能为空或空白", nameof(userName)); } } // 4. 创建自定义异常 public void GoodPractice4() { throw new InsufficientFundsException(100, 50); }
// 1. 不要捕获所有异常而不处理 public void BadPractice1() { try { DoWork(); } catch // 不好的做法 - 吞掉所有异常 { // 空的catch块 } } // 2. 不要使用异常控制流程 public void BadPractice2(string input) { try { int value = int.Parse(input); // 不好的做法 } catch { value = 0; } } // 好的做法 public void GoodAlternative(string input) { if (int.TryParse(input, out int value)) { // 使用value } else { value = 0; } } // 3. 不要抛出System.Exception public void BadPractice3() { throw new Exception("错误"); // 不好的做法 } // 好的做法 public void GoodPracticeAlternative() { throw new InvalidOperationException("操作无效"); }
try { ProcessData(); } catch (HttpException ex) when (ex.StatusCode == 404) { Console.WriteLine("资源未找到"); } catch (HttpException ex) when (ex.StatusCode >= 500) { Console.WriteLine("服务器错误"); } catch (HttpException ex) { Console.WriteLine($"HTTP错误: {ex.StatusCode}"); } // 使用日志记录的异常过滤器 private static bool LogException(Exception ex) { Console.WriteLine($"[LOG] {ex.Message}"); return false; // 返回false让异常继续传播 } try { RiskyOperation(); } catch (Exception ex) when (LogException(ex)) { // 不会执行到这里,因为过滤器返回false }
class Program { static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; try { RunApplication(); } catch (Exception ex) { Console.WriteLine($"应用程序错误: {ex.Message}"); } } static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) { var ex = e.ExceptionObject as Exception; Console.WriteLine($"未处理异常: {ex?.Message}"); // 记录日志、发送通知等 } static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { Console.WriteLine($"未观察的任务异常: {e.Exception.Message}"); e.SetObserved(); // 标记为已观察,防止进程终止 } }
public async Task ProcessAsync() { try { await Task.Delay(1000); throw new InvalidOperationException("异步操作失败"); } catch (InvalidOperationException ex) { Console.WriteLine($"异步错误: {ex.Message}"); throw; // 重新抛出 } } // 多个异步任务 public async Task ProcessMultipleAsync() { var tasks = new List<Task> { Task.Run(() => throw new InvalidOperationException("任务1失败")), Task.Run(() => throw new ArgumentException("任务2失败")), Task.Run(() => { }) }; try { await Task.WhenAll(tasks); } catch { foreach (var task in tasks) { if (task.IsFaulted) { Console.WriteLine($"任务错误: {task.Exception?.InnerException?.Message}"); } } } } // 使用AggregateException public void HandleAggregateException() { try { Parallel.For(0, 10, i => { if (i == 5) throw new InvalidOperationException($"索引 {i} 错误"); }); } catch (AggregateException ex) { foreach (var inner in ex.InnerExceptions) { Console.WriteLine($"内部错误: {inner.Message}"); } } }
public class ExceptionHandlingDemo { private readonly ILogger logger; public ExceptionHandlingDemo(ILogger logger) { this.logger = logger; } public Result<T> ExecuteSafely<T>(Func<T> operation, string operationName) { try { var result = operation(); return Result<T>.Success(result); } catch (BusinessException ex) { logger.LogWarning($"业务异常 [{operationName}]: {ex.ErrorCode} - {ex.Message}"); return Result<T>.Failure(ex.Message, ex.ErrorCode); } catch (ArgumentException ex) { logger.LogWarning($"参数错误 [{operationName}]: {ex.Message}"); return Result<T>.Failure(ex.Message, "ERR_INVALID_ARGUMENT"); } catch (IOException ex) { logger.LogError($"IO错误 [{operationName}]: {ex.Message}"); return Result<T>.Failure("系统繁忙,请稍后重试", "ERR_IO"); } catch (Exception ex) { logger.LogCritical($"未预期错误 [{operationName}]: {ex}"); return Result<T>.Failure("系统错误,请联系管理员", "ERR_INTERNAL"); } } public async Task<Result<T>> ExecuteSafelyAsync<T>(Func<Task<T>> operation, string operationName) { try { var result = await operation(); return Result<T>.Success(result); } catch (BusinessException ex) { logger.LogWarning($"业务异常 [{operationName}]: {ex.ErrorCode} - {ex.Message}"); return Result<T>.Failure(ex.Message, ex.ErrorCode); } catch (Exception ex) when (ex is OperationCanceledException) { logger.LogInformation($"操作取消 [{operationName}]"); return Result<T>.Failure("操作已取消", "ERR_CANCELED"); } catch (Exception ex) { logger.LogCritical($"未预期错误 [{operationName}]: {ex}"); return Result<T>.Failure("系统错误,请联系管理员", "ERR_INTERNAL"); } } } // 结果模式 public class Result<T> { public bool IsSuccess { get; } public T Value { get; } public string ErrorMessage { get; } public string ErrorCode { get; } private Result(bool isSuccess, T value, string errorMessage, string errorCode) { IsSuccess = isSuccess; Value = value; ErrorMessage = errorMessage; ErrorCode = errorCode; } public static Result<T> Success(T value) => new Result<T>(true, value, null, null); public static Result<T> Failure(string message, string code) => new Result<T>(false, default, message, code); } // 使用 public class OrderService { private readonly ExceptionHandlingDemo exceptionHandler; public Result<Order> PlaceOrder(OrderRequest request) { return exceptionHandler.ExecuteSafely(() => { ValidateRequest(request); var order = CreateOrder(request); SaveOrder(order); return order; }, "PlaceOrder"); } private void ValidateRequest(OrderRequest request) { if (request == null) throw new ArgumentNullException(nameof(request)); if (request.Items == null || !request.Items.Any()) throw new BusinessException("订单不能为空", "ERR_EMPTY_ORDER"); } private Order CreateOrder(OrderRequest request) => new Order(); private void SaveOrder(Order order) { } }
1. 异常捕获顺序:分析以下代码的输出结果:
<code csharp>
try
{
throw new ArgumentNullException("test");
}
catch (ArgumentException ex)
{
Console.WriteLine("ArgumentException");
}
catch (NullReferenceException ex)
{
Console.WriteLine("NullReferenceException");
}
</code>
2. 自定义异常:创建ValidationException自定义异常,包含:
3. 安全除法:编写SafeDivide方法,返回Result<double>,处理除以零的情况。
4. 重试机制:实现带重试的ExecuteWithRetry方法:
5. 事务处理:实现一个简单的TransactionScope:
6. API异常中间件:为ASP.NET Core编写异常处理中间件:
7. 断路器模式:实现Circuit Breaker模式:
8. 全局异常处理框架:设计完整的异常处理框架:
本章学习了C#异常处理:
良好的异常处理是健壮应用程序的关键。