C# Cannot use ref or out parameter inside an anonymous method body

Okay, I’ve found that it actually is possible with pointers if in unsafe context:

public static class IntEx {
    unsafe public static Action CreateIncrementer(int* reference) {
        return () => {
            *reference += 1;
        };
    }
}

However, the garbage collector can wreak havoc with this by moving your reference during garbage collection, as the following indicates:

class Program {
    static void Main() {
        new Program().Run();
        Console.ReadLine();
    }

    int _i = 0;
    public unsafe void Run() {
        Action incr;
        fixed (int* p_i = &_i) {
            incr = IntEx.CreateIncrementer(p_i);
        }
        incr();
        Console.WriteLine(_i); // Yay, incremented to 1!
        GC.Collect();
        incr();
        Console.WriteLine(_i); // Uh-oh, still 1!
    }
}

One can get around this problem by pinning the variable to a specific spot in memory. This can be done by adding the following to the constructor:

    public Program() {
        GCHandle.Alloc(_i, GCHandleType.Pinned);
    }

That keeps the garbage collector from moving the object around, so exactly what we’re looking for. However then you’ve got to add a destructor to release the pin, and it fragments the memory throughout the lifetime of the object. Not really any easier. This would make more sense in C++, where stuff doesn’t get moved around, and resource management is par the course, but not so much in C# where all that is supposed to be automatic.

So looks like the moral of the story is, just wrap that member int in a reference type and be done with it.

(And yes, that’s the way I had it working before asking the question, but was just trying to figure out if there was a way I could get rid of all my Reference<int> member variables and just use regular ints. Oh well.)

Leave a Comment

tech