ChatGPT解决这个技术问题 Extra ChatGPT

Is it bad practice to return from within a try catch finally block?

So I came across some code this morning that looked like this:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Now this code compiles fine and works as it should, but it just doesn't feel right to return from within a try block, especially if there's an associated finally.

My main issue is what happens if the finally throws an exception of it's own? You've got a returned variable but also an exception to deal with... so I'm interested to know what others think about returning from within a try block?

One benefit of this style is that you don't have to declare x outside the try block. You can keep its declaration close to its use.

m
mmx

No, it's not a bad practice. Putting return where it makes sense improves readability and maintainability and makes your code simpler to understand. You shouldn't care as finally block will get executed if a return statement is encountered.


N
Nicolas R

The finally will be executed no matter what, so it doesn't matter.


No, in fact, it's not just plugging out, there are some exceptions called async exceptions like StackOverflowException, ThreadAbortException and OutOfMemoryException which might cause the finally block not to be executed. Read about constrained execution regions for handling these scenarios.
C
Conrad

Personally, I would avoid this kind of coding as I don't feel like seeing return statements before finally statements.

My mind is simple and it process things rather linearly. Therefore when I walk through the code for dry running, I will have tendency to think that once I can reach the return statement, everything follow doesn't matter which obviously is pretty wrong in this case (not that it would affect the return statement but what the side effects could be).

Thus, I would arrange the code so that the return statement always appear after the finally statements.


C
Community

This may answer your question

What really happens in a try { return x; } finally { x = null; } statement?

From reading that question it sounds like you can have another try catch structure in the finally statement if you think it might throw an exception. The compiler will figure out when to return the value.

That said, it might be better to restructure your code anyway just so it doesn't confuse you later on or someone else who may be unaware of this as well.


hmmm very interesting. So that means it's safe, but does that mean it should be avoided?
Personally I think it makes the readability of your code a bit difficult and that alone would be enough to make me figure out some other way to structure the code. But really it's just personal preference.
I tend to agree with your personal preference :)
I think that the return is fine where it is. The method will return the value, unless an exception is thrown; doesn't matter if the exception arises in the finally cleanup code.
Note that the restriction on returning from finally is not present in Java (but I think the restriction is a good one - kudos to C#).
I
Ifeanyi Echeruo

Functionally there is no difference.

However there is one reason for not doing this. Longer methods with several exit points are often more difficult to read and analyze. But that objection has more to do with return statements than catch and finally blocks.


I would challenge this as you could end up with more nesting that also makes it harder to read an a higher cyclomatic complexity
B
BeWarned

In your example either way is equivalent, I wouldn't even be suprised if the compiler generated the same code. If an exception happens in the finally block you have the same issues whether you put the return statement in block or outside of it.

The real question is stylistically which is best. I like to write my methods so that there is only one return statement, this way it is easier to see the flow out of the method, it follows that I also like to put the return statement last so it is easy to see that it is the end of the method and this what it returns.

I think with the return statement so neatly placed as the last statement, others are less likely to come and sprinkle multiple returns statements into other parts of the method.