General Exception Handling Strategy for .NET

2020-02-09 03:32发布

I’m used to having try/catch blocks in every method. The reason for this is so that I can catch every exception at the point of infraction and log it. I understand, from my reading and conversations with others, that this isn’t a popular view. One should only catch what one is prepared to handle. However, if I don’t catch at the point of infraction, then it would be possible to never log that infraction and know about it. Note: When I do catch and don’t handle, I still throw. This allows me to let the exception propagate to something that will handle it, yet still let me log it at the point of infraction.

So... How does one avoid try/catch in every method, yet still log the error at the point at which it occurred?

11条回答
仙女界的扛把子
2楼-- · 2020-02-09 04:06

OK, having read all the answers saying you should have a single try/catch at the top level, I'm going to weigh in with an alternative view.

I wouldn't put a try/catch in every method, far from it. But I would use a try/catch around sections of code that I expected to fail (e.g. opening a file), and where I wanted to add additional information to the exception (to be logged higher up the chain).

A stack trace saying and a message saying "permission denied" might be enough to allow you as a programmer to figure out what went wrong, but my goal is to provide the user with meaningful information, such as "Could not open file 'C:\lockedfile.txt'. Permission denied.".

As in:

private void DoSomethingWithFile(string filename)
{
    // Note: try/catch doesn't need to surround the whole method...

    if (File.Exists(filename))
    {
        try
        {
            // do something involving the file
        }
        catch (Exception ex)
        {
            throw new ApplicationException(string.Format("Cannot do something with file '{0}'.", filename), ex);
        }
    }
}

I'd also like to mention that even the people saying "only have one try/catch" would presumably still use try/finally throughout their code, since that's the only way to guarantee proper cleanup, etc.

查看更多
SAY GOODBYE
3楼-- · 2020-02-09 04:08

Realistically, avoid granular try/catches. Allow the exception to traverse upwards in the stack and be caught in as high a level as possible. If you have a specific point of concern, then place logging in the immediate catch, if you are worried about the exception cascading - although you would still be able to resolve these by drilling into the inner exceptions.

Exception handling should not be an afterthought. Make sure that you do it consistently. I have seen a lot of people put a broad try/catch from the beginning to the end of every method and catch the general exception. People think that this helps them get more information, when in fact, it doesn't. More is less in some cases, as less is more. I never get tired of the axiom that "Exceptions should be used to note exceptional behavior." Recover if you can, and try to reduce the number of overall exceptions. Nothing is more frustrating when you are trying to troubleshoot an issue and seeing hundreds of the same NullReferenceException, or similar, when something goes wrong.

查看更多
闹够了就滚
4楼-- · 2020-02-09 04:11

You can see everything at stack trace - no need to try/catch every method.

Stick to few rules:

  1. Use try/catch only if you want to use a custom exception type
  2. Define a new exception type only if upper levels needs to know that
  3. Try/catch at top level instead of doing that for each method
查看更多
迷人小祖宗
5楼-- · 2020-02-09 04:14

To do it at the point of occurrence, you would still need a try/catch. But you don't necessarily need to catch the exceptions everywhere. They propagate up the call stack, and when they are caught, you get a stack trace. So if a problem emerges, you can always add more try/catches as needed.

Consider checking out one of the many logging frameworks that are available.

查看更多
爷、活的狠高调
6楼-- · 2020-02-09 04:14

Exceptions are implemented so that they have no cost unless thrown.

This means to me that performance ramifications is not a strong argument against. Exceptional conditions usually are ... exceptional.

查看更多
走好不送
7楼-- · 2020-02-09 04:15
  1. Catching and rethrowing an exception that you cannot handle is nothing more than a waste of processor time. If you can't do anything with or about the exception, ignore it and let the caller respond to it.
  2. If you want to log every exception, a global exception handler will do just fine. In .NET, the stack trace is an object; its properties can be inspected like any other. You can write the properties of the stack trace (even in string form) to your log of choice.
  3. If you want to ensure that every exception is caught, a global exception handler should do the trick. In point of fact, no application should be without one.
  4. Your catch blocks should only catch exceptions that you know that you can gracefully recover from. That is, if you can do something about it, catch it. Otherwise, let the caller worry about it. If no callers can do anything about it, let the global exception handler catch it, and log it.
查看更多
登录 后发表回答