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.
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.
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.
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.
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.
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);
}
}
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(); });
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With