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

后端 未结 28 2549
时光说笑
时光说笑 2020-11-28 03:44

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 e

相关标签:
28条回答
  • 2020-11-28 04:15

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

    0 讨论(0)
  • 2020-11-28 04:17

    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;
    })();
    
    0 讨论(0)
  • 2020-11-28 04:18

    Traditionally, in C-style languages, what happens inside the curly braces stays inside the curly braces. I think that having the lifetime of a variable stretch across scopes like that would be unintuitive to most programmers. You can achieve what you want by enclosing the try/catch/finally blocks inside another level of braces. e.g.

    ... code ...
    {
        string s = "test";
        try
        {
            // more code
        }
        catch(...)
        {
            Console.Out.WriteLine(s);
        }
    }
    

    EDIT: I guess every rule does have an exception. The following is valid C++:

    int f() { return 0; }
    
    void main() 
    {
        int y = 0;
    
        if (int x = f())
        {
            cout << x;
        }
        else
        {
            cout << x;
        }
    }
    

    The scope of x is the conditional, the then clause and the else clause.

    0 讨论(0)
  • 2020-11-28 04:18

    The answer, as everyone has pointed out, is pretty much "that's how blocks are defined".

    There are some proposals to make the code prettier. See ARM

     try (FileReader in = makeReader(), FileWriter out = makeWriter()) {
           // code using in and out
     } catch(IOException e) {
           // ...
     }
    

    Closures are supposed to address this as well.

    with(FileReader in : makeReader()) with(FileWriter out : makeWriter()) {
        // code using in and out
    }
    

    UPDATE: ARM is implemented in Java 7. http://download.java.net/jdk7/docs/technotes/guides/language/try-with-resources.html

    0 讨论(0)
  • 2020-11-28 04:22

    Because the try block and the catch block are 2 different blocks.

    In the following code, would you expect s defined in block A be visible in block B?

    { // block A
      string s = "dude";
    }
    
    { // block B
      Console.Out.WriteLine(s); // or printf or whatever
    }
    
    0 讨论(0)
  • 2020-11-28 04:22

    In the specific example you've given, initialising s can't throw an exception. So you'd think that maybe its scope could be extended.

    But in general, initialiser expressions can throw exceptions. It wouldn't make sense for a variable whose initialiser threw an exception (or which was declared after another variable where that happened) to be in scope for catch/finally.

    Also, code readability would suffer. The rule in C (and languages which follow it, including C++, Java and C#) is simple: variable scopes follow blocks.

    If you want a variable to be in scope for try/catch/finally but nowhere else, then wrap the whole thing in another set of braces (a bare block) and declare the variable before the try.

    0 讨论(0)
提交回复
热议问题