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
In Python they are visible in the catch/finally blocks if the line declaring them didn't throw.
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;
})();
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.
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
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
}
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.