Bill McCarthy recently asked me a question that’s come up a number of times both internally and externally: why can’t a Catch or Finally block access local variables declared in a Try block? In other words, why doesn’t the following work?
Dim i As Integer = 5
There are four answers to the question: the practical answer, the simple answer, the complex answer and the real answer.
THE PRACTICAL ANSWER: The question is moot because changing it now would potentially break code by changing the binding path. For example:
Private i As Integer
Dim i As Integer
Throw New NullReferenceException()
i = 5
THE SIMPLE ANSWER: Catch and Finally blocks are not children of the Try block, they’re siblings. You can see this by the indentation style and by convention. And the normal scoping rules are that sibling blocks cannot see each other’s locals.
THE COMPLEX ANSWER: You can still say “Yes, but you could still have made an exception in this case, right?” True. However, requiring Catch/Finally variables to be placed outside of the Try block generally results in better code by emphasizing the initial state of the variable (since an exception can occur almost at any time, so the initial state is the only thing you can assume). For example, the following code has a bug — if the File constructor throws an exception, then the Close call is going to throw one too.
Dim F As File = New File(“foo.txt”)
THE REAL ANSWER: You may find both of these arguments unpersuasive, which is fine — a quick search on Google quickly found similar debates around Java and I’m sure other languages have them too. The real answer is that it’s a judgment call and certainly one that we’ll probably be arguing about from here until eternity…