开发者

Try..Catch blocks always expensive? [duplicate]

开发者 https://www.devze.com 2022-12-17 01:26 出处:网络
This question already has answers here: Closed 12 years ago. Possible Duplicate: Do try/catch blocks hurt performance when exceptions are not thrown?
This question already has answers here: Closed 12 years ago.

Possible Duplicate:

Do try/catch blocks hurt performance when exceptions are not thrown?

Hey everyone, Just a quick question about try..catch block开发者_运维知识库s. I've heard they're expensive to use and shouldn't be used as part of a program's flow. However, in order to validate email addresses, I'm using the following code.

        try
        {
            MailAddress checkEmail = new MailAddress(testEmail);

            return true;
        }
        catch
        {
            return false;
        }

Due to prior validation, I don't many exceptions to be caught unless it's an attempt to bypass validation. My question is, are Try...Catch blocks only expensive if an exception is caught, or is it always expensive regardless of whether any exception is thrown?

Thanks

EDIT : Thanks for all the replies. I've decided that since the checking (in C#) isn't very expensive, I'll stick with this method. It's mainly because an actual exception being thrown is rare since there are prior validation steps that ensure no one accidentally enters an invalid email address.


In general, in today's implementations, entering a try block is not expensive at all (this was not always true). However, throwing and handling an exception is usually a relatively expensive operation. So, exceptions should normally be used for exceptional events, not normal flow control.

Performance is only one factor to consider, though, especially in the modern world. If (for instance) you're doing something once in response to a user action, it probably doesn't matter from a performance standpoint whether you use an exception even when you could have done a proactive check instead, provided the exception happens quickly enough the user isn't jolted.¹ But if you're doing something in a tight loop that's going to run hundreds of thousands of times, or you're writing a web application that may need to handle a huge load, you'd probably want to avoid using an exception for a normal case.


¹ More than a decade ago I was responsible for enhancements to a .Net 1.1 "no touch deployment" application in which the first exception thrown took fully three seconds. This was a sufficient problem in one use case involving opening a file the user had asked for which might reasonably not be there that I had to add a check for file existence prior to trying to open the file, which is normally poor programming practice (just try to open the file and handle the exception if that fails), purely because the user experience waiting for that exception to get built was so poor. But that's probably not the world we live in now.


They are pretty cheap unless there is an exception. So you should avoid them when an exception is expected, as in your example above.

I think exceptions on bad user input are generally unwise. Exceptions on out of memory or other unexpected failures are fine.


Just to play devils advocate - I have found a great use for using Exceptions for flow control: The 'cancel' button.

If you have a function running on some service that may take 10-120 minutes, which is doing a bunch of different things, I've found that doing if(hasCanceled) throw new JobCancelledException() inside of my Log() function (which logs at each step that I'm at) to work just friggan awesome. It bails out of the current execution of code and stops running the job - exactly what I need. I'm sure there's some better way to do it, maybe somehow using events - but for my case it works great (especially since jobs are not regularly cancelled).

Other then that though - I'm 100% in agreement that Exceptions should never be used as a flow control tool..

@Kornel - I have two words for that post... Holy $hit =)

here's a simple pseudo code sample:

Class Job
{
       Public Run(param1,param2,etc...)
       {
             Try
            {
                   Log("Doing Something")
                   DoSomething()

                         Log("Doing Another")
                         DoAnother()

                         Log("This keeps going, etc, inside of these function we make the same Log calls where it makes sense")
                         Etc()
                   }
                   Catch(JobCancelledException)
                   {
                        status="Cancelled"
                   }
            }

              Private Log(ByVal str As String)
              {
                      MessateToUser(str)

                      if(hasCancelled)
                          throw new JobCancelledException
            }

             private SomeEvent_WhenUserPushesCancelButton()
             {
                       hasCancelled=True
             }
}


Exceptions are only expensive if an exception is thrown. I'm sure there is some very minimal cost to setting up up a Try..Catch block but it is by far outweighed by the cost of not catching the exception at all and having your program crash. As others have pointed out, Try..Catch blocks should only be used for exceptional circumstances.


The overhead of the try block is very low, so if no exception is thrown then there should be no noticeable penalty. The main overhead that occurs when an exception is thrown is the stack walk that takes place looking for a handler - since you are caching the exception so close to the source, I doubt there will be much of a performance issue. Ideally though you would be able to validate your inputs properly beforehand, but email validation is fairly complicated so it may well not be worth it in this case.


It's only expensive if the exception is thrown, but that's not an excuse to use exceptions as normal flow control.

If you can pre-validate something to avoid an exception occurring in the first place, then do so. E.g. instead of what you posted, something like this would be preferable:

string invalidAddress = "notvalid@@@@@@lolzors.bomb";
return MailAddressValidator.IsValid(invalidAddress ); // doesn't cause exception

The exception to the rule is when you'd have to roll your own version of a complicated method (e.g. something found in the base class library that doesn't have a TryParse method) just to avoid an exception that, in the grand scheme of things, just doesn't matter.

If you are unsure, profile using representative data. If it's a user entering data in a client app form every other second, it won't matter. However, if it's a service for processing batches of thousands of email addresses that could come from anywhere, you ought to be sure of your assumptions.


try..catch blocks should never be used as a tool for program flow control.

Read this thread if you're unconvinced.


In general, modern compilers impose only a minimal cost on try blocks unless an exception is thrown. They still shouldn't be used for program flow control, as they aren't as obvious as standard flow constructs. An exception is essentially equivalent to a COME FROM statement.


While it is true that you should never use try..catch for program flow control, I am not aware of any performance issues IF no exceptions are actually thrown in the code


This is language-dependent, but as far as I know in Java, if no exception is thrown, there is next to no performance cost to having a try/catch.

So in your example of using pre-validated email addresses, what you have is fine.

0

精彩评论

暂无评论...
验证码 换一张
取 消