In C# and in Java (and possibly other languages as well), variables declared in a "try" block are not in scope in the corresponding "catch" or "finally" blocks. For example, the following code does not compile:
try {
String s = "test";
// (more code...)
}
catch {
Console.Out.WriteLine(s); //Java fans: think "System.out.println" here instead
}
In this code, a compile-time error occurs on the reference to s in the catch block, because s is only in scope in the try block. (In Java, the compile error is "s cannot be resolved"; in C#, it's "The name 's' does not exist in the current context".)
The general solution to this issue seems to be to instead declare variables just before the try block, instead of within the try block:
String s;
try {
s = "test";
// (more code...)
}
catch {
Console.Out.WriteLine(s); //Java fans: think "System.out.println" here instead
}
However, at least to me, (1) this feels like a clunky solution, and (2) it results in the variables having a larger scope than the programmer intended (the entire remainder of the method, instead of only in the context of the try-catch-finally).
My question is, what were/are the rationale(s) behind this language design decision (in Java, in C#, and/or in any other applicable languages)?
Variables in try block So, if you declare a variable in try block, (for that matter in any block) it will be local to that particular block, the life time of the variable expires after the execution of the block. Therefore, you cannot access any variable declared in a block, outside it.
Try block contains the code that might throw an exception. Catch block contains the exception handler for exceptions in the try block. The finally block contains the critical code that will execute regardless of whether the exception has occurred or not.
Nope, not at all. Its not mandatory to put catch after try block, unless and until the try block is followed by a finally block. Just remember one thing, after try, a catch or a finally or both can work.
Two things:
Generally, Java has just 2 levels of scope: global and function. But, try/catch is an exception (no pun intended). When an exception is thrown and the exception object gets a variable assigned to it, that object variable is only available within the "catch" section and is destroyed as soon as the catch completes.
(and more importantly). You can't know where in the try block the exception was thrown. It may have been before your variable was declared. Therefore it is impossible to say what variables will be available for the catch/finally clause. Consider the following case, where scoping is as you suggested:
try
{
throw new ArgumentException("some operation that throws an exception");
string s = "blah";
}
catch (e as ArgumentException)
{
Console.Out.WriteLine(s);
}
This clearly is a problem - when you reach the exception handler, s will not have been declared. Given that catches are meant to handle exceptional circumstances and finallys must execute, being safe and declaring this a problem at compile time is far better than at runtime.
How could you be sure, that you reached the declaration part in your catch block? What if the instantiation throws the exception?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With