Would you ever NOT catch an exception, or throw an exception that won't be caught?

前端 未结 14 850
感情败类
感情败类 2021-01-03 09:49

I\'ve dealt with instances where I would throw/rethrow an exception knowing that the code surrounding it would catch the specific exception. But is there any time you would

相关标签:
14条回答
  • 2021-01-03 09:54

    Generally, and certainly in early iterations of your application, don't catch the exception. More often than not, the recovery from an exception will require a business rule of some sort, and, more often than not, those business rules are not defined for you. If you "handle" the exception instead of letting the application die then you will most likely be inventing business rules for your customer. Not good.

    The general pattern of catching every exception just for the sake of catching it has caused me more headaches than I can count. It usually happens that someone puts some sort of generic exception handling code throughout the application, which inevitably ends up hiding a bug or creating some behavior that is unwanted. (incidentally, catching and then not rethrowing is even worse.)

    So, I'd suggest that you ask instead: "When should I catch an exception?"

    0 讨论(0)
  • 2021-01-03 09:54

    Firstly, there absolutely are situations where it is better to not catch an exception.

    Sometimes, an exception can sometimes tell you that your program is in an unknown state. There are a number of exceptions where this is pretty much intrinsically true given the exception type. A NullReferenceException essentially tells you "there is a bug". And by catching such an exception, you may hide the bug, which sounds good in the short term, but in the long term you'd be happier to fix it. The product may not crash, but it certainly won't have the expected behaviour.

    But this is also true for exception types we invent for ourselves. Sometimes, the fact that exception A has been thrown should be "impossible" - and yet it has happened, so there's a bug.

    Also, something very important happens when you catch an exception: the finally blocks for the whole call stack inside the try block (and anything it calls) will be executed. What do those finally blocks do? Well, anything. And if the program is in an unknown state, I really do mean anything. They could erase valuable customer data from the disk. They could throw more exceptions. They could corrupt data in memory, making the bug impossible to diagnose.

    So when an exception indicates an unknown state, you don't want to run any more code, so whatever you do, don't catch the exception. Let it fly past, and your program will terminate harmlessly, and Windows Error Reporting will be able to capture the state of the program as it was when the problem was originally detected. If you catch the exception, you will cause more code to execute, which will screw up the state of the program further.

    Secondly, should you throw an exception knowing it won't be caught? I think that question misunderstands the nature of reusable methods. The whole idea of a method is that it has a "contract" that it follows: it accepts certain parameters and returns a certain value, plus also it throws certain exceptions under certain conditions. That's the contract - it's up to the caller what they do with it. For some callers, exception A might indicate a recoverable condition. For other callers, it might indicate a bug. And from what I said above, it should be clear that if an exception indicates a bug, it must not be caught.

    And if you're wondering what this means for the Microsoft Enterprise Library's Exception Handling Block: yes, it's pretty broken. They tell you to catch (Exception x) and then decide whether to rethrow based on your policy; too late - the finally blocks have already executed by that point. Don't do that.

    0 讨论(0)
  • 2021-01-03 09:55

    Here's the thing ... it is about "layers", or "encapsulation", or "low coupling". At some place in your codebase, you're writing a method to do something. Say it's a public method. Therefore, it should not assume much or anything about the caller ... rather, it should merely do the job it is supposed to do, regardless of who is calling it and what context the caller is in.

    And if, for some reason, it cannot complete its job, then it needs to tell the caller "Sorry, I couldn't do that, and here's why". Exceptions are an excellent mechanism to let it tell the caller that (not the only mechanism, but the best mechanism I've ever seen for most cases).

    So, when you throw the exception, you have no idea whether it will be caught or not ... because you're exposing a public method and you have no idea who might choose to call it and why.

    The catching of the exception is the job of the "context". For example, say you're writing a library with public methods that might throw exceptions. Then, say you're using that library from a Windows Forms app. The Windows Forms app might catch exceptions and show a message box to the user.

    But later, you might use the same library from a Windows Service. The Service would be more likely to catch the exception, log it, return an error to the original caller, but keep running so it can process further requests.

    So the exception is like a contractual agreement between the caller and the provider. The provider says, "I'll either do the job or tell you why I can't. What you do from there is your own business." And the caller says, "OK, if you can't do the job, just tell me why, and I'll decide what to do in that case."

    0 讨论(0)
  • 2021-01-03 09:55

    If your application is primarily going to be used by other clients and is not standalone, it generally makes sense to throw exceptions if a condition arises that you don't know how to (or don't want to) handle, and there's no sensible way for you to recover from it. Clients should be able to decide how they want to handle any exceptions that you might throw.

    On the other hand, if your application is the endpoint, throwing an exception essentially becomes a notification mechanism to alert people that something has gone terribly wrong. In such cases, you need to consider a few things:

    • How important is the continued running of the application? Is this error really unrecoverable? Throwing an exception and terminating your program is not something you want to be doing on the space shuttle.

    • Are you using exceptions as a proxy for real logging? There's almost never a reason to do this; consider a real logging mechanism instead. Catch the exception and have the logger work out what happened.

    • What are you trying to convey by throwing the exception yourself? Ask yourself what the value in throwing a new exception is, and consider carefully whether there isn't a better way to do what you want.

    • Not catching an exception may leave resources in a bad state. If you don't gracefully exit, things are generally not cleaned up for you. Make sure you understand what you're doing if you need to do this -- and if you're not going to catch it, at least consider a try-finally block so you can do some tidying up.

    0 讨论(0)
  • 2021-01-03 09:56

    It depends on the type of application. Web applications can continue running even after exceptions have bubbled up to the execution context.

    It is common practice to 'throw/rethrow' an exception if you catch the exception at a level where it can't be dealt with. But, you would almost always add context to the issue, at the very least add some logging at the higher level to say that it was caught and rethrown.

    for example

    A calls B calls C (throws exception)

    B catches/rethrows

    A catches.

    In this case, you would want B to add some logging so that you can differentiate between B generating and throwing an error, and C generating and throwing an error. That would allow you a greater ability to debug and fix problems later.

    In general you will almost NEVER want an exception to kill your program. The best practice is to catch the except and exit gracefully. This allows you to save any currently open information and release resources that are being used so they don't become corrupted. If you intend to exit, you can create your own 'core-dump' information report that includes the things you were doing when you caught the fatal exception.

    If you let the exception kill your process you are eliminating your chance to get custom tailored crash information, and you are also skipping the part where you provide the user with a friendly error message and then exit.

    So, I would recommend ALWAYS catching exceptions, and never voluntarily letting them run amok in your program.

    EDIT

    If you are writing a library, you have to choose ahead of time whether your function will throw an exception, or be exception safe. In those cases, sometimes you will throw an exception and have no idea if the calling party will catch it. But in that case, catching it is not your responsibility, as long as the api declares that the function could throw exceptions. (I'm looking for a word that means 'could possibly throw exception'... anyone know what it is? It's going to bug me all day.)

    0 讨论(0)
  • 2021-01-03 10:03

    If I need a moderately large system that is somehow processing data in what I believe to be a consistent manner.

    And

    Somewhere along the line, I detect that the application's state has become inconsistent.

    And

    The system doesn't (yet) know how to fix the inconsistency and recover gracefully

    Then, yes, I would throw an exception with as much detail as possible and cause the application to die as quickly as possible, to avoid doing any further harm to the data. If it can be recovered, it'd be important not to exacerbate the problem by trying feebly to cover up the mess.

    Later along the line, once the chain of events that led to the inconsistency is better understood, I higher facility can catch that exception, repair the state, and continue with minimal interruption.

    0 讨论(0)
提交回复
热议问题