Share via


C# out parameter assignment trivia

I have the following code

         static void foo(out int i)
        {
            try {
                /*...*/
                i = 5;
            }
            catch (Exception) {
                /*...*/
            }
            finally {
                /*...*/
            }
        }

this fails to compile with the message "The out parameter 'i' must be assigned to before control leaves the current method". I have assigned I thought. But a bit more thought helped me in seeing through this and when I removed the catch part it worked (and so it did when I moved the i assignment out of the try.

         static void foo(out int i)
        {
            try {
                /*...*/
                i = 5;
            }
            finally {
                /*...*/
            }
        }

I'd guess that the compiler uses a variant of Definite Assignment to figure out that a variable is definitely assigned before it leaves the function. Since there is a catch in foo in the first case, it might happen that the code before i assignment might throw an exception and the catch block catches and ignores it. In that case the i will reach the caller of foo un-assigned.

If you put an empty throw in the catch block signalling that you'll be rethrowing the exception then the compilation goes through. I found this to be very cool.

Comments

  • Anonymous
    May 10, 2007
    assign a default value outside the try, catch, finally
  • Anonymous
    May 17, 2007
    I wonder why the second case works. The value of i is not reassigned in the finlally {} block.
  • Anonymous
    May 17, 2007
    The second example works because the try block will either successfully assign a value to i or throw an exception up to the caller. The first example doesn't work because it is possible to throw an exception before assigning a value to i, catch and recover from the exception, and then return i. This would not be type safe (what does i point to before it is initialized?), so the compiler disallows it.