Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Temporarily change a variable's value

Tags:

c#

In an API implementation I'm currently hacking on, there's the need to repeatedly change some variables temporarily, before doing some task, and change them back after the task is done to whatever they were before.

The current code looks like this:

var _oldValue = _variable;
_variable = tempValue;
try
{
  doIt();
}
finally
{
  _variable = oldValue;
}

Doing this a lot is annoying, ugly, hard to maintain, and buries the actual algorithms under a lot of clutter that's just implementation artifacts.

In C++, I would make a class which stores the old value somewhere during construction, and restores it in its destructor:

{
  temp_value tmp(variable_, temp_val);
  do_it();
}

When trying to do something similar in C# I failed because apparently C# can't store references to other objects in classes.

So what would I have to do in C# to remove that clutter?

P.S.: Feel free to add any other tags you see fit. I failed to come up with any.

like image 415
sbi Avatar asked Mar 28 '11 20:03

sbi


People also ask

How do you temporarily change a variable in Python?

Using a temporary variable The simplest way to swap the values of two variables is using a temp variable. The temp variables is used to store the value of the fist variable ( temp = a ). This allows you to swap the value of the two variables ( a = b ) and then assign the value of temp to the second variable.

Can we change value in runtime?

How can we change the value of a constant at run time? You don't, it is the principle of constant. The keyword constant is used explicitly to say that the value never change at runtime. And any attempt to do so is reported as an error at compile time.

Can you change the value of a variable?

You can "assign a new value" to your variable, but you can't change the value itself, unlike an array or object, which you can modify without affecting the variable binding.

Can a variable store a value that can be changed?

Variables are data values that can change when the user is asked a question, for example, their age. Variables may change during program execution. A variable is a memory location . It has a name that is associated with that location.


3 Answers

While I agree with Eric Lippert on ideal solution there are cases when on forced to temporay change state of varable and execute some actions. I.e. there are several examples of such requirement in SharePoint object model, so it is not possible to redesign code to avoid it.

Below is code that can be used to temporary cahnge value and restor it with using statement. Use of using for such non-release-unmanged-resources purposes is contentios, so use you judgment if such approach works for you:

Usage sample:

using(TemporaryChange(true, myValue, v => myValue = v))
{
 // code to run while "myValue" is changed to "true"
}

Class:

class TemporaryChange<V> : IDisposable
{
    private V original;
    private Action<V> setValue;

    internal TemporaryChange(V value, V currentValue, Action<V> setValue)
    {
        this.setValue = setValue;
        this.original = currentValue;
        this.setValue(value);
    }

    void IDisposable.Dispose()
    {
        this.setValue(this.original);
    }
}
like image 168
Alexei Levenkov Avatar answered Nov 05 '22 15:11

Alexei Levenkov


Why not create a method that does it for you, and then pass a Lamda to it?

private void SaveGlobalsAndDoSomething(Action doit)
{
    var _oldValue = _variable;
    _variable = tempValue;
    try
    {
        doit();
    }
    finally
    {
        _variable = _oldValue;
    }
}

And to use it:

SaveGlobalsAndDoSomething(() => { DoSomething(); });

Edit in response to comment:

That doit sometimes returns a value isn't a problem. We're not passing DoSomething to the method. We're passing { DoSomething(); } to the method. So you can easily write:

int returnValue;
SaveGlobalsAndDoSomething(() => { returnValue = DoSomething(); });
like image 27
Jim Mischel Avatar answered Nov 05 '22 15:11

Jim Mischel


The fact that you are considering doing a variety of horrible, horrible things to solve this problem is indicative that you shouldn't be in this situation in the first place. If you're in a situation where code depends on mutating and then unmutating state then you have a bad design. Fix the real design problem rather than trying to come up with a clever way to continue using the bad architecture.

What I do when I'm in this situation is clone my state. Suppose you are doing this:

class Frobber
{
    State state;
    ...
    void M()
    {
         ...
         try
         {
             oldstate = state;
             state = newstate;
             this.DoIt();
         }
         finally
         {
             state = oldstate;
         }
    }

Instead do this:

class Frobber
{
    State state;
    ...
    void M()
    {
         ...
         Frobber newFrobber = new Frobber(newstate);
         newFrobber.DoIt();
         ...

Instead of mutating a variable and changing it back, make a whole new variable. Throw away the new variable when you're done with it. The old variable doesn't need to be mutated back because it never changed.

like image 28
Eric Lippert Avatar answered Nov 05 '22 14:11

Eric Lippert