Reference To Variable, Not To Object

82 views Asked by At

I'd like if I could make a reference that will always point to that specific variable rather than to the object (or memory location more accurately) that the variable is currently representing.

As an example let's say I have the following program, I want to create a reference to MyClass a so that it always returns whatever value is in MyClass a at all times, even if that value changes. I have some code that looks like.

class MyClass
{
    public int value = 0;
}

class Program
{
    static MyClass saved; //maintained and used by the following two functions
    static void StoreReference(MyClass input)
    {
        saved = input;
    }

    static void SetValue()
    {
        saved.value = 42;
    }

    static void Main(string[] args)
    {
        //A couple arbitrary classes I'd like to have references to
        MyClass a = new MyClass();
        MyClass b = new MyClass();

        StoreReference(a);
        a = b;
        SetValue();
        Console.Write(a.value); //should print 42, instead prints 0 since it reads in the original object a was set to
    }
}

Is there anything that can do this in C#, or anything that can prevent the variable from being assigned to a new memory location (so that the above code would return an error at a = b)?

2

There are 2 answers

0
Glorfindel On

You can check whether saved already has a value or not:

static void StoreReference(MyClass input)
{
    if (saved != null) {
        return;
    }
    saved = input;
}
0
Matthew Haugen On

I see quite a few responses here that suggest the use of a readonly field or ref parameter, but I'm not sure I completely understand why those are relevant. So please excuse me if I don't understand your question.

But from what I see, you're looking to negate the effect of the assignment (a = b;), which is not possible.

The only alternative is to switch to using saved instead of a in your call to Console.Write

static void Main(string[] args)
{
    MyClass a = new MyClass();
    MyClass b = new MyClass();

    StoreReference(a);
    a = b;
    SetValue();
    Console.Write(saved.value);
}

That will work, and it will print 42 like you wanted. But I get that that isn't what you're looking for.

There's no language feature, though, that will let that code compile and let you do what you want to. And that's a good thing. That's why the compiler runs these checks (or part of it, anyway). If you forgot you had this fictional modifier to make a local variable read-only and you wrote out the assignment expecting it to work like it would everywhere else in any C language, it would be very confusing.

Now, onto what others have been saying, I'm really not sure I get why ref has come up at all, but readonly: that's a perfectly reasonable modifier to put on your field, but it:

  1. Only works on fields, which means it'll protect saved but not a local variable.
  2. Only lets values be set in the constructor, which isn't where you're trying to set it here.

So if you do intend to use it, and don't get me wrong it's great for what it does, do be wary of those two facts. You'll need some re-architecting. And honestly, I'd avoid that in a static void Main(...) anyway--constructor nonsense there might get confusing.

In any event, I think you might be trying to solve a problem that shouldn't be there in the first place. It might help to see a real-world use-case for this, but from what you've given us, it doesn't sound like it's something that will be possible, and unfortunately with good reason.


For what it's worth, your title and opening paragraph make me think you're looking for a pointer to a pointer, which isn't allowable in managed C#. I've never ventured into unmanaged C#, but it's allowed in C++ so I suspect it might be supported there. In any event, the rest of your question doesn't really remind me of that, so this may not be relevant.