[ACCEPTED]-Why is try {...} finally {...} good; try {...} catch{} bad?-try-catch-finally

Accepted answer
Score: 365

The big difference is that try...catch will swallow 5 the exception, hiding the fact that an error 4 occurred. try..finally will run your cleanup code and 3 then the exception will keep going, to be 2 handled by something that knows what to 1 do with it.

Score: 63

"Finally" is a statement of "Something you 20 must always do to make sure program state 19 is sane". As such, it's always good form 18 to have one, if there's any possibility 17 that exceptions may throw off the program 16 state. The compiler also goes to great lengths 15 to ensure that your Finally code is run.

"Catch" is 14 a statement of "I can recover from this 13 exception". You should only recover from 12 exceptions you really can correct - catch 11 without arguments says "Hey, I can recover 10 from anything!", which is nearly always 9 untrue.

If it were possible to recover from 8 every exception, then it would really be 7 a semantic quibble, about what you're declaring 6 your intent to be. However, it's not, and 5 almost certainly frames above yours will 4 be better equipped to handle certain exceptions. As 3 such, use finally, get your cleanup code 2 run for free, but still let more knowledgeable 1 handlers deal with the issue.

Score: 33

Because when that one single line throws 11 an exception, you wouldn't know it.

With 10 the first block of code, the exception will 9 simply be absorbed, the program will continue to 8 execute even when the state of the program 7 might be wrong.

With the second block, the 6 exception will be thrown and bubbles up but the reader.Close() is 5 still guaranteed to run.

If an exception 4 is not expected, then don't put a try..catch 3 block just so, it'll be hard to debug later 2 when the program went into a bad state and 1 you don't have an idea why.

Score: 21

Finally is executed no matter what. So, if 9 your try block was successful it will execute, if 8 your try block fails, it will then execute 7 the catch block, and then the finally block.

Also, it's 6 better to try to use the following construct:

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

As 5 the using statement is automatically wrapped 4 in a try / finally and the stream will be 3 automatically closed. (You will need to 2 put a try / catch around the using statement 1 if you want to actually catch the exception).

Score: 7

While the following 2 code blocks are equivalent, they 6 are not equal.

try
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}
  1. 'finally' is intention-revealing code. You declare to the compiler and to other programmers that this code needs to run no matter what.
  2. if you have multiple catch blocks and you have cleanup code, you need finally. Without finally, you would be duplicating your cleanup code in each catch block. (DRY principle)

finally blocks are special. The 5 CLR recognizes and treats code withing a 4 finally block separately from catch blocks, and 3 the CLR goes to great lengths to guarantee 2 that a finally block will always execute. It's 1 not just syntactic sugar from the compiler.

Score: 5

I agree with what seems to be the consensus 12 here - an empty 'catch' is bad because it 11 masks whatever exception might have occurred 10 in the try block.

Also, from a readability 9 standpoint, when I see a 'try' block I assume 8 there will be a corresponding 'catch' statement. If 7 you are only using a 'try' in order to ensure 6 resources are de-allocated in the 'finally' block, you 5 might consider the 'using' statement instead:

using (StreamReader reader = new StreamReader('myfile.txt'))
{
    // do stuff here
} // reader.dispose() is called automatically

You can use 4 the 'using' statement with any object that 3 implements IDisposable. The object's dispose() method 2 gets called automatically at the end of 1 the block.

Score: 5

Use Try..Catch..Finally, if your method knows how to handle 14 the exception locally. The Exception occurs 13 in Try, Handled in Catch and after that 12 clean up is done in Finally.

In case if your 11 method doesn't know how to handle the exception 10 but needs a cleanup once it has occurred 9 use Try..Finally

By this the exception is propagated 8 to the calling methods and handled if there 7 are any suitable Catch statements in the 6 calling methods.If there are no exception 5 handlers in the current method or any of 4 the calling methods then the application 3 crashes.

By Try..Finally it is ensured that the local 2 clean up is done before propagating the 1 exception to the calling methods.

Score: 3

The try..finally block will still throw 23 any exceptions that are raised. All finally does 22 is ensure that the cleanup code is run before 21 the exception is thrown.

The try..catch with 20 an empty catch will completely consume any 19 exception and hide the fact that it happened. The 18 reader will be closed, but there's no telling 17 if the correct thing happened. What if 16 your intent was to write i to the file? In 15 this case, you won't make it to that part 14 of the code and myfile.txt will be empty. Do all 13 of the downstream methods handle this properly? When 12 you see the empty file, will you be able 11 to correctly guess that it's empty because 10 an exception was thrown? Better to throw 9 the exception and let it be known that you're 8 doing something wrong.

Another reason is 7 the try..catch done like this is completely 6 incorrect. What you are saying by doing 5 this is, "No matter what happens, I can 4 handle it." What about StackOverflowException, can you clean 3 up after that? What about OutOfMemoryException? In general, you 2 should only handle exceptions that you expect 1 and know how to handle.

Score: 2

If you don't know what exception type to 9 catch or what to do with it, there's no 8 point in having a catch statement. You should 7 just leave it for a higher-up caller that 6 may have more information about the situation 5 to know what to do.

You should still have 4 a finally statement in there in case there 3 is an exception, so that you can clean up 2 resources before that exception is thrown 1 to the caller.

Score: 2

From a readability perspective, it's more 8 explicitly telling future code-readers "this 7 stuff in here is important, it needs to 6 be done no matter what happens." This is 5 good.

Also, empty catch statements tend 4 to have a certain "smell" to them. They 3 might be a sign that developers aren't thinking 2 through the various exceptions that can 1 occur and how to handle them.

Score: 2

Finally is optional -- there's no reason 2 to have a "Finally" block if there are no 1 resources to clean up.

Score: 2

Taken from: here

Raising and catching exceptions 51 should not routinely occur as part of the 50 successful execution of a method. When developing 49 class libraries, client code must be given 48 the opportunity to test for an error condition 47 before undertaking an operation that can 46 result in an exception being raised. For 45 example, System.IO.FileStream provides a 44 CanRead property that can be checked prior 43 to calling the Read method, preventing a 42 potential exception being raised, as illustrated 41 in the following code snippet:

Dim str As 40 Stream = GetStream() If (str.CanRead) Then 'code 39 to read stream End If

The decision of whether 38 to check the state of an object prior to 37 invoking a particular method that may raise 36 an exception depends on the expected state 35 of the object. If a FileStream object is 34 created using a file path that should exist 33 and a constructor that should return a file 32 in read mode, checking the CanRead property 31 is not necessary; the inability to read 30 the FileStream would be a violation of the 29 expected behavior of the method calls made, and 28 an exception should be raised. In contrast, if 27 a method is documented as returning a FileStream 26 reference that may or may not be readable, checking 25 the CanRead property before attempting to 24 read data is advisable.

To illustrate the 23 performance impact that using a "run 22 until exception" coding technique can 21 cause, the performance of a cast, which 20 throws an InvalidCastException if the cast 19 fails, is compared to the C# as operator, which 18 returns nulls if a cast fails. The performance 17 of the two techniques is identical for the 16 case where the cast is valid (see Test 8.05), but 15 for the case where the cast is invalid, and 14 using a cast causes an exception, using 13 a cast is 600 times slower than using the 12 as operator (see Test 8.06). The high-performance 11 impact of the exception-throwing technique 10 includes the cost of allocating, throwing, and 9 catching the exception and the cost of subsequent 8 garbage collection of the exception object, which 7 means the instantaneous impact of throwing 6 an exception is not this high. As more exceptions 5 are thrown, frequent garbage collection 4 becomes an issue, so the overall impact 3 of the frequent use of an exception- throwing 2 coding technique will be similar to Test 1 8.05.

Score: 2

It's bad practice to add a catch clause 1 just to rethrow the exception.

Score: 2

If you'll read C# for programmers you will understand, that 24 the finally block was design to optimize 23 an application and prevent memory leak.

The 22 CLR does not completely eliminate leaks... memory 21 leaks can occur if program inadvertently 20 keep references to unwanted objects

For 19 example when you open a file or database 18 connection, your machine will allocate memory 17 to cater that transaction, and that memory 16 will be kept not unless the disposed or 15 close command was executed. but if during 14 transaction, an error was occurred, the 13 proceeding command will be terminated not 12 unless it was inside the try.. finally.. block.

catch was different 11 from finally in the sense that, catch was design 10 to give you way to handle/manage or interpret 9 the error it self. Think of it as person 8 who tells you "hey i caught some bad 7 guys, what do you want me to do to them?" while 6 finally was designed to make sure that your resources 5 was properly placed. Think of it of someone 4 that whether or not there is some bad guys 3 he will make sure that your property was 2 still safe.

And you should allow those two 1 to work together for good.

for example:

try
{
  StreamReader reader=new  StreamReader("myfile.txt");
  //do other stuff
}
catch(Exception ex){
 // Create log, or show notification
 generic.Createlog("Error", ex.message);
}
finally   // Will execute despite any exception
{
  reader.Close();
}
Score: 1

With finally, you can clean up resources, even 8 if your catch statement throws the exception 7 up to the calling program. With your example 6 containing the empty catch statement, there 5 is little difference. However, if in your 4 catch, you do some processing and throw 3 the error, or even just don't even have 2 a catch at all, the finally will still get 1 run.

Score: 1

Well for one, it's bad practice to catch 6 exceptions you don't bother to handle. Check 5 out Chapter 5 about .Net Performance from Improving .NET Application Performance and Scalability. Side note, you should probably 4 be loading the stream inside the try block, that 3 way, you can catch the pertinent exception 2 if it fails. Creating the stream outside 1 the try block defeats its purpose.

Score: 0

Amongst probably many reasons, exceptions 3 are very slow to execute. You can easily 2 cripple your execution times if this happens 1 a lot.

Score: 0

The problem with try/catch blocks that catch 13 all exceptions is that your program is now 12 in an indeterminate state if an unknown 11 exception occurs. This goes completely against 10 the fail fast rule - you don't want your 9 program to continue if an exception occurs. The 8 above try/catch would even catch OutOfMemoryExceptions, but 7 that is definitely a state that your program 6 will not run in.

Try/finally blocks allow 5 you to execute clean up code while still 4 failing fast. For most circumstances, you 3 only want to catch all exceptions at the 2 global level, so that you can log them, and 1 then exit out.

Score: 0

The effective difference between your examples 32 is negligible as long as no exceptions are 31 thrown.

If, however, an exception is thrown 30 while in the 'try' clause, the first example 29 will swallow it completely. The second 28 example will raise the exception to the 27 next step up the call stack, so the difference 26 in the stated examples is that one completely 25 obscures any exceptions (first example), and 24 the other (second example) retains exception 23 information for potential later handling 22 while still executing the content in the 21 'finally' clause.

If, for example, you were 20 to put code in the 'catch' clause of the 19 first example that threw an exception (either 18 the one that was initially raised, or a 17 new one), the reader cleanup code would 16 never execute. Finally executes regardless of what 15 happens in the 'catch' clause.

So, the main 14 difference between 'catch' and 'finally' is 13 that the contents of the 'finally' block 12 (with a few rare exceptions) can be considered 11 guaranteed to execute, even in the face of an unexpected 10 exception, while any code following a 'catch' clause 9 (but outside a 'finally' clause) would not 8 carry such a guaranty.

Incidentally, Stream 7 and StreamReader both implement IDisposable, and 6 can be wrapped in a 'using' block. 'Using' blocks 5 are the semantic equivalent of try/finally 4 (no 'catch'), so your example could be more 3 tersely expressed as:

using (StreamReader reader = new  StreamReader("myfile.txt"))
{
  int i = 5 / 0;
}

...which will close 2 and dispose of the StreamReader instance 1 when it goes out of scope. Hope this helps.

Score: 0

try {…} catch{} is not always bad. It's 4 not a common pattern, but I do tend to use 3 it when I need to shutdown resources no 2 matter what, like closing a (possibly) open 1 sockets at the end of a thread.

More Related questions