How to accomplish scoped variable reset in C#? - c#

One common pattern I see and use frequently in C++ is to temporarily set a variable to a new value, and then reset it when I exit that scope. In C++, this is easily accomplished with references and templated scope classes, and allows for increased safety and prevention of errors where the variable is set to a new value, then reset to an incorrect assumed initial value.
Here is a simplified example of what I mean (in C++):
void DoSomething()
{
// The following line captures GBL.counter by reference, stores its current
// value, and sets it to 1
ScopedReset<int> resetter(GBL.counter, 1);
// In this function and all below, GBL.counter will be 1
CallSomethingThatNeedsCounterOf1();
// When I hit the close brace, ~ScopedReset will be called, and it will
// reset GBL.counter to it's previous value
}
Is there any way to do this in C#? I've found the hard way that I can't capture a ref parameter inside an IEnumerator or a lambda, which were my first two thoughts. I don't want to use the unsafe keyword if possible.

The first challenge to doing this in C# is dealing with non-deterministic destruction. Since C# doesn't have destructors you need a mechanism to control scope in order to execute the reset. IDisposable helps there and the using statement will mimic C++ deterministic destruction semantics.
The second is getting at the value you want to reset without using pointers. Lambdas and delegates can do that.
class Program
{
class ScopedReset<T> : IDisposable
{
T originalValue = default(T);
Action<T> _setter;
public ScopedReset(Func<T> getter, Action<T> setter, T v)
{
originalValue = getter();
setter(v);
_setter = setter;
}
public void Dispose()
{
_setter(originalValue);
}
}
static int counter = 0;
static void Main(string[] args)
{
counter++;
counter++;
Console.WriteLine(counter);
using (new ScopedReset<int>(() => counter, i => counter = i, 1))
Console.WriteLine(counter);
Console.WriteLine(counter);
}
}

Can you not simply copy the reference value to a new local variable, and use this new variable throughout your method, i.e. copy value by value?
Indeed, changing it from a ref to regular value parameter will accomplish this!

I don't think you can capture a ref paramenter to a local variable, and have it stay a ref - a local copy will be created.
GBL.counter is effectively an implicit, hidden parameter to CallSomethingThatNeedsCounterOf1. If you could convert it to a regular, declared paraemter your problem would go away. Also, if that would result in to many parameters, a solution would be a pair of methods which set up and reset the environment so that CallSomethingThatNeedsCounterOf1() can run.
You can create a class that calls the SetUp method in its constructor and the Reset method in Dispose(). You can use this class with the using statement, to aproximate the c++ behaviour. You would, however, have to create one of these classes for each scenario.

Related

Explicitly tell compiler to stop optimization and keep an unused variable in C#

I have a method that return someCalssObject.SomeProperty. In the program, the value of someCalssObject.SomeProperty is lazily initialized (i.e. the data is not computed until it is used).
Due to some architectural issue in the program (not in my hand to fix it), if I return this lazily initialized property someCalssObject.SomeProperty, some of the values gets already disposed by the time program really needs to use the data present inside someCalssObject.SomeProperty. And hence, the program generates unexpected outputs.
To resolve the use, I have introduced a dummy variable (dummyVariable) which forces the computation of the data for the property someCalssObject.SomeProperty.
protected override void SomeMethod()
{
//Some Code
//MUST HAVE THIS LINE (even though the CANNOT be used anywhere)
var dummyVariable = someCalssObject.SomeProperty.GetValues<float>(); //This line forces the computation of some Lazily Initialized data
// Some more code
return someCalssObject.SomeProperty;
}
With the above approach of introducing a dummy variable, the program is working fine (both in debug and release mode). But I am afraid that the compiler may/will remove the line computing dummy variable (dummyVariable ) as optimization since the variable is not used anywhere.
QUESTION: How can I tell the compiler to keep the line that is computing the dummy variable without making any change in the compilation settings? Will declaring the unused variable as static volatile a robust solution?
If you want to make sure the value of dummyVariable is not GC'ed until the function ends, you can add GC.KeepAlive(dummyVariable) at the end of your function (you may need to create a variable for your return value, too). The method does nothing, but ensures a reference to the value used as argument exists until it is called.
So that would be:
protected override void SomeMethod()
{
//Some Code
//MUST HAVE THIS LINE (even though the CANNOT be used anywhere)
var dummyVariable = someCalssObject.SomeProperty.GetValues<float>(); //This line forces the computation of some Lazily Initialized data
// Some more code
var ret = someCalssObject.SomeProperty;
GC.KeepAlive(dummyVariable);
return ret;
}

Nice way of resetting a variable

I've been finding myself doing this pattern, for large pre-existing objects we want to modify slightly to pass down to another call, but don't want to copy but don't want the caller to see the change:
ResultType f(T x, TLarge config) {
var oldVal = config.blah; // 1st line of boilerplate
config.blah = "New Value"; // 2nd line of boilerplate
try {
return g(config);
}
finally
{
config.blah = oldVal; // 3rd line of boilerplate
}
}
This gets a bit messy particularly when there's more than one variable to change.
Is there a nice way to wrap this up into a pattern? I tried using using and sticking a reference as a member to an IDisposable struct and resetting on close but that didn't work as references can't be members.
A lot of the types I'm temporarily modifying are strings and ints so this needs to work with value types.

Why doesn't my C# compiler (Visual Studio) let me do this with a try block?

I have many scenarios during my development where I want to do something such as
try
{
long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs);
}
catch ( Exception e )
{
throw e;
}
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
// ...
return presult;
but then my compiler flags the presult on the line
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
saying
The name 'presult' does not exist in the current context
If it were smart, it would understand that presult is either initialized in the try block, or the procedure is exited before presult is ever used.
Possible workarounds (none of them good):
Declare long presult; right before the try statement. This makes the compiler mad because it wrongly thinks there's a possibility of returning an unintialized variable.
Initialize it with long presult = default(long). This works, but it's bad practice because someone reading the code doesn't know whether intializing it to the default value is to work around the problem described in 1. or is because the value presult because set to the default long has some real meaning in the context of the program.
Initialize it with long? presult = null. This is semantically better because it's clear that it means "presult is meant to have no value at this point" whereas in 2. the reader has to figure out that presult has a meaningless value. The problem here is that, not only does it take extra memory to nullify a value, but I then have to change the function EvalInner to return a long? and this results in a chain of needing to change many more longs to long?s and my program ends up splattered with nullified variables; it's a complete mess of question marks haha.
Anyways, how should I be handling a case like this?
I'll go over your points one by one:
Declare long presult; right before the try statement. This makes the
compiler mad because it wrongly thinks there's a possibility of
returning an unintialized variable.
Actually, the compiler correctly determines that there is the possibility of returning an uninitialized variable. Since the variable is only set if the function on the right hand side succeeds, and since you have it in a try..catch block then there is the possibility that the function may throw and not return, therefore not initializing the variable. What the compiler is not smart enough to see is that you are catching the top level exception and throwing (in a bad way, losing the stack trace) and it should not reach the return. However there are ways to get around that (mostly during debug by dragging the execution cursor).
Initialize it with long presult = default(long). This works, but
it's bad practice because someone reading the code doesn't know
whether intializing it to the default value is to work around the
problem described in 1. or is because the value presult because set
to the default long has some real meaning in the context of the
program.
Since value types like long, int, short etc must have a value, this is not bad practice. If you want to represent them as not having a value, use the nullable versions of those types (i.e. long? presult = null).
Initialize it with long? presult = null. This is semantically better
because it's clear that it means "presult is meant to have no value
at this point" whereas in 2. the reader has to figure out that
presult has a meaningless value. The problem here is that, not only
does it take extra memory to nullify a value, but I then have to
change the function EvalInner to return a long? and this results in
a chain of needing to change many more longs to long?s and my
program ends up splattered with nullified variables; it's a complete
mess of question marks haha.
Again, the function must return a value that is a valid long, so if you want to return something that can easily be identified as an incorrect value, then return the nullable version, otherwise you have to return a valid value. Only float and double have NaN members...
Another option would be some kind of TryXXX method, where the return value is a boolean and you use an out long as a parameter to store the result.
I don't understand you problem. The compiler can't know the value of presult when you call evalNewResult that's why you need to declare it outside the try block. It's a general rule of scopes in C# and a lot of other languages.
The solution is to declare and initialize it before the try block. The question is "what value should presult have in case an exception occurs". The compiler can't ask this question himslef.
How about:
try
{
long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs);
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
// ...
return presult;
}
catch ( Exception e )
{
//Do some useful logging
throw; //Don't lose stacktrace!
}
Please check this link for more enlightment
Compilers are in the business of generating code which manages the storage of the data manipulated by that program. There are lots of different ways of generating code to manage memory, but over time two basic techniques have become entrenched.
The first is to have some sort of "long lived" storage area where the "lifetime" of each byte in the storage -- that is, the period of time when it is validly associated with some program variable -- cannot be easily predicted ahead of time. The compiler generates calls into a "heap manager" that knows how to dynamically allocate storage when it is needed and reclaim it when it is no longer needed.
The second is to have some sort of "short lived" storage area where the lifetime of each byte in the storage is well known, and, in particular, lifetimes of storages follow a "nesting" pattern. That is, the allocation of the longest-lived of the short-lived variables strictly overlaps the allocations of shorter-lived variables that come after it.
Local variables follow the latter pattern; when a method is entered, its local variables come alive. When that method calls another method, the new method's local variables come alive. They'll be dead before the first method's local variables are dead. The relative order of the beginnings and endings of lifetimes of storages associated with local variables can be worked out ahead of time.
For this reason, local variables are usually generated as storage on a "stack" data structure, because a stack has the property that the first thing pushed on it is going to be the last thing popped off.
So overall local variable are are short lived and usually stored in stack, why stack coz its efficient than others. Link for more info why stack
Why doesn't my C# compiler (Visual Studio) let me do this with a try block?
That is because braces define a scope. From Variable and Method Scope in Microsoft .NET:
If you declare a variable within a block construct such as an If statement, that variable's scope is only until the end of the block. The lifetime is until the procedure ends.
how should I be handling a case like this?
Go for option 1.
This makes the compiler mad because it wrongly thinks there's a possibility of returning an unintialized variable
Option 1 does not make the compiler mad. The compiler is always right :-)
I created the following SSCCE and it absolutely works:
using System;
namespace app1
{
class Program
{
static void Main(string[] args)
{
Presult();
}
private static long Presult()
{
long presult;
try
{
object eqtn = null;
char begidx = '\0';
int curidx = 0;
object eqtnArgs = null;
presult = EvalInner(eqtn, new Tuple<int, int>(++begidx, curidx - 1), eqtnArgs);
}
catch (Exception e)
{
throw e;
}
int result = 0;
object lastop = null;
object negateNextNum = null;
object negateNextOp = null;
result = evalNewResult(result, lastop, presult, ref negateNextNum, ref negateNextOp);
// ...
return presult;
}
private static int evalNewResult(int result, object lastop, long presult, ref object negateNextNum, ref object negateNextOp)
{
return 0;
}
private static long EvalInner(object eqtn, Tuple<int, int> tuple, object eqtnArgs)
{
return 0;
}
}
}
how should I be handling a case like this?
The correct way is your Option 1. That doesn't make compiler "mad", because in fact declaring a variable and initializing it later is allowed construct (not only for this particular case) from the very beginning, and compiler should be able to handle it correctly w/o problem.
IMO, the only drawback (or better say inconvenience) is that the keyword var cannot be used, so the type must be specified explicitly. But some people that are against using var in general would say this is indeed a good thing :-)

How closure in c# works when using lambda expressions?

In to following tutorial : http://www.albahari.com/threading/
They say that the following code :
for (int i = 0; i < 10; i++)
new Thread (() => Console.Write (i)).Start();
is non deterministic and can produce the following answer :
0223557799
I thought that when one uses lambda expressions the compiler creates some kind of anonymous class that captures the variables that are in use by creating members like them in the capturing class.
But i is value type, so i thought that he should be copied by value.
where is my mistake ?
It will be very helpful if the answer will explain how does closure work, how do it hold a "pointer" to a specific int , what code does generated in this specific case ?
The key point here is that closures close over variables, not over values. As such, the value of a given variable at the time you close over it is irrelevant. What matters is the value of that variable at the time the anonymous method is invoked.
How this happens is easy enough to see when you see what the compiler transforms the closure into. It'll create something morally similar to this:
public class ClosureClass1
{
public int i;
public void AnonyousMethod1()
{
Console.WriteLine(i);
}
}
static void Main(string[] args)
{
ClosureClass1 closure1 = new ClosureClass1();
for (closure1.i = 0; closure1.i < 10; closure1.i++)
new Thread(closure1.AnonyousMethod1).Start();
}
So here we can see a bit more clearly what's going on. There is one copy of the variable, and that variable has now been promoted to a field of a new class, instead of being a local variable. Anywhere that would have modified the local variable now modifies the field of this instance. We can now see why your code prints what it does. After starting the new thread, but before it can actually execute, the for loop in the main thread is going back and incrementing the variable in the closure. The variable that hasn't yet been read by the closure.
To produce the desired result what you need to do is make sure that, instead of having every iteration of the loop closing over a single variable, they need to each have a variable that they close over:
for (int i = 0; i < 10; i++)
{
int copy = i;
new Thread(() => Console.WriteLine(copy));
}
Now the copy variable is never changed after it is closed over, and our program will print out 0-9 (although in an arbitrary order, because threads can be scheduled however the OS wants).
As Albahari states, Although the passing arguments are value types, each thread captures the memory location thus resulting in unexpected results.
This is happening because before the Thread had any time to start, the loop already changed whatever value that inside i.
To avoid that, you should use a temp variable as Albahari stated, or only use it when you know the variable is not going to change.
i in Console.Write(i) is evaluated right when that statement is about to be executed. That statement will be executed once thread has been fully created and started running and got to that code. By that time loop has moved forward a few times and thus i can be any value by then. Closures, unlike regular functions, have visibility into local variables of a function in which it is defined (what makes them useful, and way to shoot oneself in a foot).

C# lambda, local variable value not taken when you think?

Suppose we have the following code:
void AFunction()
{
foreach(AClass i in AClassCollection)
{
listOfLambdaFunctions.AddLast( () => { PrintLine(i.name); } );
}
}
void Main()
{
AFunction();
foreach( var i in listOfLambdaFunctions)
i();
}
One might think that the above code would out the same as the following:
void Main()
{
foreach(AClass i in AClassCollection)
PrintLine(i.name);
}
However, it doesn't. Instead, it prints the name of the last item in AClassCollection every time.
It appears as if the same item was being used in each lambda function. I suspect there might be some delay from when the lambda was created to when the lambda took a snapshot of the external variables used in it.
Essentially, the lambda is holding a reference to the local variable i, instead of taking a "snapshot" of i's value when the lambda was created.
To test this theory, I tried this code:
string astr = "a string";
AFunc fnc = () => { System.Diagnostics.Debug.WriteLine(astr); };
astr = "changed";
fnc();
and, surprise, it outputs changed!
I am using XNA 3.1, and whichever version of C# that comes with it.
My questions are:
What is going on?
Does the lambda function somehow store a 'reference' to the variable or something?
Is there any way around this problem?
This is a modified closure
See: similar questions like Access to Modified Closure
To work around the issue you have to store a copy of the variable inside the scope of the for loop:
foreach(AClass i in AClassCollection)
{
AClass anotherI= i;
listOfLambdaFunctions.AddLast( () => { PrintLine(anotherI.name); } );
}
does the lambda function somehow store a 'reference' to the variable or something?
Close. The lambda function captures the variable itself. There is no need to store a reference to a variable, and in fact, in .NET it is impossible to permanently store a reference to a variable. You just capture the entire variable. You never capture the value of the variable.
Remember, a variable is a storage location. The name "i" refers to a particular storage location, and in your case, it always refers to the same storage location.
Is there anyway around this problem?
Yes. Create a new variable every time through the loop. The closure then captures a different variable every time.
This is one of the most frequently reported problems with C#. We're considering changing the semantics of the loop variable declaration so that a new variable is created every time through the loop.
For more details on this issue see my articles on the subject:
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
what is going on? does the lambda function somehow store a 'reference' to the variable or something?
Yes exactly that; c# captured variables are to the variable, not the value of the variable. You can usually get around this by introducing a temp variable and binding to that:
string astr = "a string";
var tmp = astr;
AFunc fnc = () => { System.Diagnostics.Debug.WriteLine(tmp); };
especially in foreach where this is notorious.
Yes, the lambda stores a reference to the variable (conceptually speaking, anyway).
A very simple workaround is this:
foreach(AClass i in AClassCollection)
{
AClass j = i;
listOfLambdaFunctions.AddLast( () => { PrintLine(j.name); } );
}
In every iteration of the foreach loop, a new j gets created, which the lambda captures.
i on the other hand, is the same variable throughout, but gets updated with every iteration (so all the lambdas end up seeing the last value)
And I agree that this is a bit surprising. :)
I've been caught by this one as well, as said by Calgary Coder, it is a modified closure. I really had trouble spotting them until I got resharper. Since it is one of the warnings that resharper watches for, I am much better at identifying them as I code.

Categories