C#通过继承捕获异常问题:自定义异常未匹配预期捕获分支
你的问题根源在于自定义异常类的命名和.NET框架自带的System.ApplicationException重名了,导致代码里的catch块行为完全不符合预期:
当你写catch (ApplicationException ex)时,编译器默认会匹配框架内置的System.ApplicationException,而你自己定义的ApplicationException是完全独立的另一个类型——你的CustomException继承的是你自己的ApplicationException,并不是系统自带的那个,所以抛出CustomException时,系统的ApplicationException捕获块根本识别不了它,直接就落到最通用的Exception捕获块里了。
解决方法
方案1:重命名自定义异常类(推荐)
这是最稳妥的做法,既能彻底避免命名冲突,也符合.NET的设计规范(微软早已不推荐使用System.ApplicationException,建议自定义异常直接继承Exception)。
修改你的异常类代码:
// 改成一个独特的名称,比如AppBusinessException public class AppBusinessException : Exception { public AppBusinessException(string message) : base(message) { } public AppBusinessException(string message, Exception innerException) : base(message, innerException) { } } public class CustomException: AppBusinessException { private static readonly string MESSAGE = "customMessage"; public CustomException(): base(MESSAGE) { } }
然后更新控制器的catch块,捕获你新命名的异常基类:
public async Task<HttpResponseMessage> Get([FromUri]GetDto getDto) { try { var response = await _application.Get(getDto); return Request.CreateResponse(HttpStatusCode.OK, response); } catch (AppBusinessException ex) { return Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message); } catch (Exception) { return Request.CreateResponse(HttpStatusCode.InternalServerError, "There was an error on the request."); } }
方案2:明确指定自定义异常的命名空间(应急方案)
如果暂时不想改名,你需要在catch块里明确指定自定义异常的完整命名空间,让编译器知道要捕获你自己定义的类型:
假设你的自定义异常位于YourApplication.Exceptions命名空间下,修改控制器代码:
// 先引用你的命名空间(或者直接在catch里写全限定名) using YourApplication.Exceptions; public async Task<HttpResponseMessage> Get([FromUri]GetDto getDto) { try { var response = await _application.Get(getDto); return Request.CreateResponse(HttpStatusCode.OK, response); } catch (YourApplication.Exceptions.ApplicationException ex) { return Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message); } catch (Exception) { return Request.CreateResponse(HttpStatusCode.InternalServerError, "There was an error on the request."); } }
补充说明
.NET框架中的System.ApplicationException是早期设计的产物,微软现在明确建议:自定义异常应该直接继承Exception,而不是ApplicationException。所以方案1不仅解决了你的捕获问题,也遵循了官方的最佳实践,后续维护起来更清晰。
内容的提问来源于stack exchange,提问作者mvoelcker

