问题
I don't understand why the following code produces an error. Normally I can figure things out from the language specification, but in this case I don't understand the language specification.
This isn't causing problems in my code, by the way, I just want to understand the language.
Example:
bool success;
try
{
success = true;
}
catch
{
success = false;
}
finally
{
Console.WriteLine(success); // ERROR: Local variable 'success' might not be initialized before accessing
}
This behavior appears to be true of all versions of C#, but the quotes below are from C# Language Specification 5.0.
Section 5.3.3.14 Try-finally statements
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.
Here "beginning of stmt" refers to the beginning of the entire try-finally statement, i.e. just before try
.
Section 5.3.3.15 Try-catch-finally statements
The following example demonstrates how the different blocks of a try statement (§8.10) affect definite assignment.
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
}
Can anyone explain why success
(in my example) or i
(in the language spec example) are not definitely assigned at the beginning of the finally-block?
回答1:
Simple reason is - There is no guarantee that the code in try
or catch
block will ever execute, before finally
block.
ThreadAbort
Exception can happen inside the try
block, but before assignment executes.
Runtime code executes after exception is thrown but before code in catch
blocks executes (Search for how exception handling works in .Net or "Structured Exception Handling").
Hence, code in try and catch block may never execute, before execution of finally
block.
回答2:
As Vikas said, exceptions can happen inside catch block too, passing control to the finally without running the whole catch block. There's no guarantee that either of the assignments actually completed.
Why design the language to make it easier to write bad code? Good code will catch only specific exceptions, or catch and log all but then rethrow the ones it doesn't recognize. Only bad code that catches and ignores all exceptions can even run into this case.
Besides, the fix is incredibly easy.
来源:https://stackoverflow.com/questions/28755949/in-c-why-is-a-variable-not-definitely-assigned-at-the-beginning-of-a-finally-b