tags:

views:

278

answers:

2

Hey folks,

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.

+3  A: 

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).

Reed Copsey
But I suppose there is no way to dynamically store something? Like wrapping it in a delegate or such?
Xeon06
You can always copy it. You can do a closure, but that (indirectly) stores a reference to the containing class...
Reed Copsey
I had been looking all over the Net for how to do this. Would you be so kind as to edit your answer showing a small example please? For now I'm using Reflection, but it gives things like Monitor.Watch(new Property(Game, "FPS")), I'd rather be able to just do Monitor.Watch(Game.FPS) or something simpler at least.
Xeon06
Can you show some code that demonstrates exactly how your (current) code works? I'd recommend posting that (as a new question), asking for advice on how to improve it (ie: remove magic strings, etc).
Reed Copsey
http://stackoverflow.com/questions/2256145/improve-property-monitoring-code
Xeon06
@Xeon06: Gave you a very good option in your other post...
Reed Copsey
In fact, it is not possible in the underlying CLR to have "ref" fields. It'll be much harder to perform verification for a system that allows references to stack-based variables. C# can't do much about that.
Mehrdad Afshari
I thought there would be an answer using boxing, but I see that you can't really modify or watch the field directly. You box a reference to the int, not the field =P
Merlyn Morgan-Graham
+10  A: 

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. 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.)

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.

Eric Lippert