C#异常过滤器通过when子句在catch前判断是否处理异常,相比传统if判断更高效、语义更清晰,避免不必要的资源开销并保持栈跟踪完整,适用于精细化处理特定异常场景。

C#的异常过滤器,简单来说,就是给你的
catch
catch
if
使用C#异常过滤器非常直观,它通过在
catch
when
when
比如,你可能遇到这样的场景:一个方法可能会抛出
IOException
IOException
IOException
try
{
// 尝试读取一个可能不存在的文件
string content = System.IO.File.ReadAllText("nonexistent.txt");
Console.WriteLine(content);
}
catch (System.IO.FileNotFoundException ex) // 针对FileNotFoundException,这已经是更精确的了
{
Console.WriteLine($"文件未找到:{ex.Message}");
}
catch (System.IO.IOException ex) when (ex.Message.Contains("磁盘空间不足")) // 针对IOException,但只处理特定消息的
{
Console.WriteLine($"磁盘空间不足,无法操作文件:{ex.Message}");
}
catch (System.IO.IOException ex) // 其他所有IOException
{
Console.WriteLine($"发生了其他IO错误:{ex.Message}");
// 这里可以选择重新抛出,或者记录日志
// throw;
}
catch (Exception ex)
{
Console.WriteLine($"发生了未知错误:{ex.Message}");
}你看,
when (ex.Message.Contains("磁盘空间不足"))IOException
true
catch
false
catch
catch
这比在
catch (IOException ex)
if (ex.Message.Contains("磁盘空间不足")) { ... } else { throw; }catch
这确实是个好问题,很多人会觉得,在
catch
if
一个最显著的区别在于执行时机和资源消耗。当你使用
catch (Exception ex) when (condition)
when
catch
condition
false
catch
catch
catch
when
相比之下,传统的
catch (Exception ex)
if (condition) { /* handle */ } else { throw; }catch
if
throw
另一个关键点是栈跟踪的完整性。当你在
catch
throw
throw;
catch
catch
从代码可读性来说,
when
catch
catch
在我看来,异常过滤器并非万能药,但它在某些特定场景下,简直是神来之笔,能让代码变得异常清晰和健壮。
首先,有条件地记录日志而不中断流程。设想你有一个关键的服务,它可能会因为各种原因抛出异常,其中有些是你可以忽略的(比如客户端断开连接),但你又想记录下来。你可以在一个通用的
catch (Exception ex)
when (ex is ClientDisconnectedException)
catch
其次,基于异常内部属性进行精细化处理。很多时候,我们捕获的异常类型是一样的,但其内部的错误码、消息或者其他自定义属性却能区分出不同的处理逻辑。例如,处理数据库操作时,
SqlException
catch (SqlException ex)
if (ex.Number == ...)
catch (SqlException ex) when (ex.Number == 1205) // 死锁错误
{
Console.WriteLine("检测到数据库死锁,尝试重试...");
// 可以在这里实现重试逻辑
}
catch (SqlException ex) when (ex.Number == 2627) // 主键冲突
{
Console.WriteLine("数据已存在,无法插入...");
}
// 其他SqlException由下一个catch处理这让每个
catch
再来,区分瞬态错误和永久性错误。在网络通信或分布式系统中,很多错误是瞬态的(比如网络抖动、临时服务不可用),可以通过重试来解决;而有些是永久性的(比如配置错误、权限不足),重试也无济于事。异常过滤器可以帮助你快速识别并分类这些错误:
catch (HttpRequestException ex) when (IsTransientError(ex.StatusCode))
{
Console.WriteLine($"检测到瞬态HTTP错误:{ex.Message},准备重试...");
}
catch (HttpRequestException ex) // 其他HTTP错误
{
Console.WriteLine($"检测到永久性HTTP错误:{ex.Message}");
// 记录并向上抛出
}这里的
IsTransientError
最后,当你的异常处理逻辑变得复杂,需要避免嵌套的 if-else if
catch
虽然异常过滤器功能强大,但如果不正确使用,也可能引入新的问题。这里我总结了一些常见的陷阱和一些我个人认为的最佳实践。
常见的陷阱:
在 when
when
when
when
catch
when
when
catch
if
throw
when
catch
when
对 when
when
catch
catch
when
when
true
catch
最佳实践:
保持 when
when
结合特定异常类型使用:异常过滤器最强大的用法是与特定的异常类型结合。不要在一个通用的
catch (Exception ex)
when
catch (SqlException ex)
when
用于细化而不是替代所有 if
if
catch
if
if
catch
利用自定义异常的属性:如果你定义了自定义异常类型,可以在其中添加特定的属性来携带更多上下文信息(比如错误码、业务ID等)。这样,在
when
public class MyCustomException : Exception
{
public int ErrorCode { get; }
public MyCustomException(string message, int errorCode) : base(message)
{
ErrorCode = errorCode;
}
}
// ...
try
{
// ...
throw new MyCustomException("业务逻辑错误", 1001);
}
catch (MyCustomException ex) when (ex.ErrorCode == 1001)
{
Console.WriteLine($"处理自定义错误码1001:{ex.Message}");
}
catch (MyCustomException ex) when (ex.ErrorCode == 1002)
{
Console.WriteLine($"处理自定义错误码1002:{ex.Message}");
}这种模式让你的异常处理逻辑不仅能区分异常类型,还能深入到异常的业务含义层面,从而实现更精准的错误处理。它真的能让你的异常处理代码变得既专业又易读。
以上就是C#的异常过滤器是什么?如何使用?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号