Reputation:
string foo;
try
{
foo = "test"; // yeah, i know ...
}
catch // yeah, i know this one too :)
{
foo = null;
}
finally
{
Console.WriteLine(foo); // argh ... @#!
}
Console.WriteLine(foo); // but nothing to complain about here
Besides it's not BP (catching-routing) - but this is the best isolation I can get.
But I get nice waves telling me "danger, danger - might be uninitialized".
How comes?
Edit:
Please do not suggest "Simply put a string foo = string.Empty;
at the 'declaration'". I'd like to declare it, but just do the assignment on time!
Upvotes: 6
Views: 449
Reputation: 1076
Some background from the C# specification (5.3.3.14):
For a try statement stmt of the form:
try try-block finally finally-block
(...)
The definite assignment state of v at the beginning of finally-block is the same as the definite assignment state of v at the beginning of stmt.
Edit Try-Catch-Finally(5.3.3.15):
Definite assignment analysis for a try-catch-finally statement (...) is done as if the statement were a try-finally statement enclosing a try-catch statement
The following example demonstrates how the different blocks of a try statement (§8.10) affect definite assignment.
class A
{
static void F()
{
int i, j;
try {
goto LABEL;
// neither i nor j definitely assigned
i = 1;
// i definitely assigned
}
catch {
// neither i nor j definitely assigned
i = 3;
// i definitely assigned
}
finally {
// neither i nor j definitely assigned
j = 5;
// j definitely assigned
}
// i and j definitely assigned
LABEL:;
// j definitely assigned
}
}
I just thought of an example that shows the problem better:
int i;
try
{
i = int.Parse("a");
}
catch
{
i = int.Parse("b");
}
finally
{
Console.Write(i);
}
Upvotes: 3
Reputation: 2548
Declare your string foo
at class level it will solve the problem
EDIT : or
string foo = "default";
try
{
foo = "test";
}
catch (Exception)
{
foo = null;
}
finally
{
Console.WriteLine(foo);
}
Upvotes: 0
Reputation: 13148
I think the problem probably is that there is the case where both the try
and catch
throw exceptions. In that case, the finally
should still be reached, but with an uninitialized foo
. Since in that case, the rest of the code will not be reached (the exception that was thrown in the catch
block takes us out of the method after the finally
), this does not present a problem for the code after the finally
. That code can only be reached if either the try
or catch
blocks ran.
Since there is always the case that every single assignment to foo
threw an exception, and since in that case the finally
block will always run anyway, there is always the possibility of foo
being uninitialized.
As far as I can tell, the only way around this is to provide an initialization value for foo
.
Upvotes: 2
Reputation: 173
Try this one:
string foo = null;
try
{
foo = "test"; // yeah, i know ...
}
catch // yeah, i know this one too :)
{
}
finally
{
Console.WriteLine(foo); // argh ... @#!
}
Console.WriteLine(foo); // but nothing to complain about here
Upvotes: -2
Reputation: 301037
You will have to change the first line to string foo = null
or initialize as needed. As far as the compiler is concerned, there might be an exception before the foo is intialized in try block and the catch may not happen as well.
Upvotes: 2