简体   繁体   English

何时以及为什么我应该显式抛出异常

[英]When and Why I should Explicitly throw an Exception

I'm just trying to make my understanding of Exception mechanism more clear.我只是想让我对异常机制的理解更清楚。
If something goes wrong when an app is executed, the runtime automatically throws an appropriate exception.如果应用程序执行时出现问题,运行时会自动抛出适当的异常。 If it is so, then why I should sometimes make some check and explicitly throw a specific exception?如果是这样,那为什么我有时应该进行一些检查并明确抛出特定异常?
How to identify such cases (when an exception should be explicitly thrown in code)?如何识别这种情况(何时应在代码中显式抛出异常)?

I don't put any example here on purpose, because I'd like to get a general understanding of the throwing exceptions approach.我不是故意在这里举任何例子,因为我想对抛出异常的方法有一个大致的了解。

I think the general approach should be Fail Fast - you want to identify and handle invalid program conditions as soon as possible, this would mean not just when a particular input is needed within your program logic but as soon as you "receive" this input (which could be way earlier in time and/or lines of codes).我认为一般方法应该是快速失败- 您希望尽快识别和处理无效的程序条件,这不仅意味着在您的程序逻辑中需要特定输入时,而且一旦您“接收”此输入(这可能在时间和/或代码行上更早)。

For ie public methods that means validating an input first, and if appropriate throw an exception if the input violates what your method expects.对于即意味着首先验证输入的公共方法,如果输入违反您的方法所期望的,则在适当的情况下抛出异常。

Generally, my rule is that if an error occurs that the code I'm writing can't specifically handle, I'll throw an exception.一般来说,我的规则是,如果发生我正在编写的代码无法专门处理的错误,我会抛出异常。 For instance, if I'm writing a function that accepts a couple of arguments, and the function is meaningless if the arguments are null I'll check for that and throw some ArgumentNullException 's For instance, if I'm writing a function that accepts a couple of arguments, and the function is meaningless if the arguments are null I'll check for that and throw some ArgumentNullException 's

Generally, a method, subroutine, component, service, or system should throw an exception only when that thing cannot do (successfully complete) whatever it was asked to do .一般来说,一个方法、子例程、组件、服务或系统应该只在它不能做(成功完成)它被要求做的任何事情时抛出异常。

"whatever it was asked to do" is somewhat subjective, of course.当然,“无论它被要求做什么”都有些主观。 As an example, if you have a method in a utility library that is named SaveFile() and it fails to save the file, but you called it from a client that is attempting to save a file to a location that might or might exist, and the client app doesn't even care if the file gets saved or not... Then the utility library SaveFile() method should still throw an exception, and the client should swallow it in the place where it was called.例如,如果您在实用程序库中有一个名为 SaveFile() 的方法,但它无法保存文件,但您从尝试将文件保存到可能存在或可能存在的位置的客户端调用它,并且客户端应用程序甚至不关心文件是否被保存......然后实用程序库 SaveFile() 方法仍然应该抛出异常,并且客户端应该在调用它的地方吞下它。

I don't know that I could express the exhaustive list, but a few good examples might include我不知道我可以表达详尽的清单,但一些很好的例子可能包括

  1. When you need to stop/alter execution for a scenario that wouldn't cause any system exceptions (if there are no foos with n bars the system is in trouble, throw a custom exception)当您需要停止/更改不会导致任何系统异常的场景的执行时(如果没有带有 n 条的 foos 系统有问题,则抛出自定义异常)

  2. When you are at a boundary where the system exception would include data that was not needed, or possibly not desirable to expose (users my not need to see everything in the stack trace, but you could log the actual exception then throw a custom exception (Data Access, Service Access, etc) that allows you to control what is propagated downstream.当您处于系统异常将包含不需要或可能不希望公开的数据的边界时(用户不需要查看堆栈跟踪中的所有内容,但您可以记录实际异常然后抛出自定义异常(数据访问、服务访问等),允许您控制向下游传播的内容。

  3. When you can add additional contextual information to an exception, ie you caught some exception and can use it as the inner exception for a new exception that includes information that can be useful for logging/debugging etc.当您可以向异常添加额外的上下文信息时,即您捕获了一些异常并可以将其用作新异常的内部异常,该异常包含对日志记录/调试等有用的信息。

You can throw exceptions whenever your application enters any exceptional state.每当您的应用程序输入任何异常 state 时,您都可以抛出异常。 There may be invariants violated ("x can never be null." is a good invariant which may be covered by an assertion or exception), Maybe something went terribly wrong.可能违反了不变量(“x 永远不可能是 null。”是一个很好的不变量,可能会被断言或异常所涵盖),也许出了什么大问题。 eg another machine sent corrupt data, Of course everything would result in some exception or error of the runtime of your choice (java, .net), but whenever your custom exception would be more concise (closer to the line of code which caused the problem, better naming. ..,) than the built-in one.例如,另一台机器发送了损坏的数据,当然一切都会导致您选择的运行时(java,.net)出现一些异常或错误,但只要您的自定义异常会更简洁(更接近导致问题的代码行) ,更好的命名...,)比内置的。 it's a possible candidate for a custom exception.它可能是自定义异常的候选者。

Theres another reason for custom exceptions: If all of your exceptions would inherit from a custom exception class, it's easier for the client to catch the exceptions he's interested in. Most of the time nobody wants to catch NPEs or stuff like that, so it may be more convenient to catch a smaller range of exceptions.自定义异常还有另一个原因:如果您的所有异常都继承自自定义异常 class,则客户端更容易捕获他感兴趣的异常。大多数时候没有人想捕获 NPE 或类似的东西,所以它可能更方便地捕获更小范围的异常。

every method has a return type (whether that type be void, int, string, car, etc.) an exception allows you to return a message to a calling context that is NOT of type T, but is of Type Exception that says "something went wrong".每个方法都有一个返回类型(无论该类型是 void、int、string、car 等)。一个异常允许您向调用上下文返回一条消息,该消息不是 T 类型,但属于异常类型,表示“某事出错”。 What went wrong is identify by the derived type (from exception, as SQLException) and message.出了什么问题是由派生类型(来自异常,如 SQLException)和消息识别的。 This creates a uniform interface (by type exception) for messaging errors.这为消息传递错误创建了一个统一的接口(按类型异常)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM