Search code examples
c#out

How does the out parameter work internally?


class fff {
    public static void jjj(out int j) {
        j = 88;
    }
}

//Main method
 int jfjf;
 fff.jjj(out jfjf);

In my main method I declare the jfjf variable which is not initialized in the runtime so I was wondering when I pass jfjf as the out argument to my jjj(out int j) method, what does the int j in the method refer to since the jfjf is not initialized?
I would like to know how this works internally.


Solution

  • Internally, the address of jfjf is passed to your method.

    For a regular (non-out) int parameter, the parameter's value is passed to the method. For example, the first statement of the following code block

    f(1);
    
    void f(int i) {
       ...
    }
    

    compiles to the following CIL (sharplab):

    IL_0000: ldc.i4.1   // Push the value 1 on the stack
    IL_0001: call void Program::'<<Main>$>g__f|0_0'(int32) // Invoke the method
    

    On the other hand, if we have an out parameter (sharplab):

    f(out int i);
    
    void f(out int i) {
        i = 0;
    }
    

    the address of i is passed to f:

    IL_0000: ldloca.s 0  // Push the address of the local variable with index 0 on the stack
    IL_0002: call void Program::'<<Main>$>g__f|0_0'(int32&)
    

    When f assigns a value to i, the value is stored at the memory address provided by the calling method:

    IL_0000: ldarg.0     // Push argument 0 (= i's address) on the stack
    IL_0001: ldc.i4.0    // Push 0 (the value we want to assign) on the stack
    IL_0002: stind.i4    // Pop the value and the address from the stack, and store the value at the address
    IL_0003: ret