6
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!

9
  • Assign a null, this is efficient and will appease the compiler, then get rid of the catch entirely. Commented May 24, 2012 at 7:12
  • @AdamHouldsworth i've mentioned that this is an isolated example, didn't i? i have to use the catch in my real scenario, because i have some other code in there :) Commented May 24, 2012 at 7:13
  • yes you did but you have yet to provide a solid argument for not initializing it with null beforehand. You stated in another comment that you didn't want to do that. Manojlds answer is likely the reason, the finally is considered out of the try scope so the MSDN docs entry still stands. Commented May 24, 2012 at 7:22
  • @AdamHouldsworth it's just against my nature to workaround the cool feature of splitted declaration and assignment/initialization - at that time i'll do this, i could argue: "why is there still splitted declaration and assignment/initialization ?? i could do a 'foo'-assignment at the start" ... :) Commented May 24, 2012 at 7:25
  • @AdamHouldsworth btw ... codinghorror.com/blog/2005/07/… Commented May 24, 2012 at 7:42

6 Answers 6

3

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); } 
Sign up to request clarification or add additional context in comments.

5 Comments

but i have try-block,catch-block,finally-block
@AndreasNiedermair I added quotes for Try-Catch-Finally.
btw, the example is misleading! the spec states: "try-finally statement enclosing a try-catch statement" ... but yes - now it is clear ... finally is just out of phase/scope ... thanks!
@AndreasNiedermair I just added an example of my own that hpefully shows the problem
which explains why finally is designed to be out of scope ... yes ... but - i could simple do another try-catch inside the catch (to catch that) :) the spec is btw really good (i just needed to think about this few sentences some minutes)
2

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.

12 Comments

The important part being the lack of guarantee on the catch, if the complier cannot guarantee it opts for the safe path - error or warning.
@AdamHouldsworth any pattern, for my scenario, to ensure the catch for the safe path? btw could you give me any spec on "the lack of guarantee on the catch"? that would be really nice!
Is there really a case where an exception is thrown, the catch block isn't executed, but the finally block is?
is maybe finally ignoring both the try and catch blocks, since it doesn't know how much of either might have executed? I don't see any reason why the finally should complain if the second Console.WriteLine call doesn't. any scenario where foo is uninitialized in the finally block, it will be uninitialized after it as well.
@AdamHouldsworth which it isn't. the point is either both should complain or neither should (in the code example given).
|
2

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.

1 Comment

i agree. but: (i believe that) the compiler would get that :) ... the real issue here is "finally is out of scope"
0

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); } 

1 Comment

@AndreasNiedermair then initialize string foo before try catch
-2

try

string foo = string.Empty; 

Comments

-2

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 

Comments