Alex Rivera | Logout

Why aren't variables declared in "try" in scope in "catch" or "finally"?

Asked 2008-09-18T17:56:23.880
165

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)?

Edit
Report

6 Answers

56

How could you be sure, that you reached the declaration part in your catch block? What if the instantiation throws the exception?

answered 2008-09-18T17:58:40.020
2

When you declare a local variable it is placed on the stack (for some types the entire value of the object will be on the stack, for other types only a reference will be on the stack). When there is an exception inside a try block, the local variables within the block are freed, which means the stack is "unwound" back to the state it was at at the beginning of the try block. This is by design. It's how the try / catch is able to back out of all of the function calls within the block and puts your system back into a functional state. Without this mechanism you could never be sure of the state of anything when an exception occurs.

Having your error handling code rely on externally declared variables which have their values changed inside the try block seems like bad design to me. What you are doing is essentially leaking resources intentionally in order to gain information (in this particular case it's not so bad because you are only leaking information, but imagine if it were some other resource? you're just making life harder on yourself in the future). I would suggest breaking up your try blocks into smaller chunks if you require more granularity in error handling.

answered 2008-09-18T18:12:41.627
2

The C# Spec (15.2) states "The scope of a local variable or constant declared in a block ist the block."

(in your first example the try block is the block where "s" is declared)

answered 2008-09-18T18:14:59.060
2

When you have a try catch, you should at the most part know that errors that it might throw. Theese Exception classes normaly tell everything you need about the exception. If not, you should make you're own exception classes and pass that information along. That way, you will never need to get the variables from inside the try block, because the Exception is self explainatory. So if you need to do this alot, think about you're design, and try to think if there is some other way, that you can either predict exceptions comming, or use the information comming from the exceptions, and then maybe rethrow your own exception with more information.

answered 2008-09-18T18:19:20.517
2

In Python they are visible in the catch/finally blocks if the line declaring them didn't throw.

answered 2008-09-19T06:00:20.113
-1

C# 3.0:

string html = new Func<string>(() =>
{
    string webpage;

    try
    {
        using(WebClient downloader = new WebClient())
        {
            webpage = downloader.DownloadString(url);
        }
    }
    catch(WebException)
    {
        Console.WriteLine("Download failed.");  
    }

    return webpage;
})();
answered 2008-09-18T23:58:27.987

Your Answer