Store a reference to a value type?

Viewed 36625

I am writing a "Monitor" object to facilitate debugging of my app. This Monitor object can be accessed at run time from an IronPython interpreter. My question is, is it possible in C# to store a reference to a value type? Say I have the following class:

class Test
{
    public int a;
}

Can I somehow store a "pointer" to "a" in order to be able to check it's value anytime? Is it possible using safe and managed code?

Thanks.

6 Answers

You cannot store a reference to a variable in a field or array. The CLR requires that a reference to a variable be in (1) a formal parameter, (2) a local, or (3) the return type of a method. C# supports (1) but not the other two.

(ASIDE: It is possible for C# to support the other two; in fact I have written a prototype compiler that does implement those features. It's pretty neat. (See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.) Of course one has to write an algorithm that verifies that no ref local could possibly be referring to a local that was on a now-destroyed stack frame, which gets a bit tricky, but its doable. Perhaps we will support this in a hypothetical future version of the language. (UPDATE: It was added to C# 7!))

However, you can make a variable have arbitrarily long lifetime, by putting it in a field or array. If what you need is a "reference" in the sense of "I need to store an alias to an arbitrary variable", then, no. But if what you need is a reference in the sense of "I need a magic token that lets me read and write a particular variable", then just use a delegate, or a pair of delegates.

sealed class Ref<T> 
{
    private Func<T> getter;
    private Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
    public T Value
    {
        get { return getter(); }
        set { setter(value); }
    }
}
...
Ref<string> M() 
{
    string x = "hello";
    Ref<string> rx = new Ref<string>(()=>x, v=>{x=v;});
    rx.Value = "goodbye";
    Console.WriteLine(x); // goodbye
    return rx;
}

The outer local variable x will stay alive at least until rx is reclaimed.

No - you can't store a "pointer" to a value type directly in C#.

Typically, you'd hold a reference to the Test instance containing "a" - this gives you access to a (via testInstance.a).

You can create ref-return delegate. This is similar to Erik's solution, except instead of getter and setter it use single ref-returning delegate.

You can't use it with properties or local variables, but it returns true reference (not just copy).

public delegate ref T Ref<T>();

class Test
{
    public int a;
}

static Ref<int> M()
{
    Test t = new Test();
    t.a = 10;

    Ref<int> rx = () => ref t.a;
    rx() = 5;
    Console.WriteLine(t.a); // 5
    return rx;
}
Related