I've seen countless posts on how variable capture pulls in variables for the creation of the closure, however they all seem to stop short of specific details and call the whole thing "compiler magic".
I'm looking for a clear-cut explanation of:
How local variables are actually captured.
The difference (if any) between capturing value types vs. reference types.
And whether there is any boxing occurring with respect to value types.
My preference would be for an answer in terms of values and pointers (closer to the heart of what happens internally), though I will accept a clear answer involving values and references as well.
Is tricky. Will come onto it in a minute.
There's no difference - in both cases, it's the variable itself which is captured.
Nope, no boxing occurs.
It's probably easiest to demonstrate how the capturing works via an example...
Here's some code using a lambda expression which captures a single variable:
using System;
class Test
{
static void Main()
{
Action action = CreateShowAndIncrementAction();
action();
action();
}
static Action CreateShowAndIncrementAction()
{
Random rng = new Random();
int counter = rng.Next(10);
Console.WriteLine("Initial value for counter: {0}", counter);
return () =>
{
Console.WriteLine(counter);
counter++;
};
}
}
Now here's what the compiler's doing for you - except that it would use "unspeakable" names which couldn't really occur in C#.
using System;
class Test
{
static void Main()
{
Action action = CreateShowAndIncrementAction();
action();
action();
}
static Action CreateShowAndIncrementAction()
{
ActionHelper helper = new ActionHelper();
Random rng = new Random();
helper.counter = rng.Next(10);
Console.WriteLine("Initial value for counter: {0}", helper.counter);
// Converts method group to a delegate, whose target will be a
// reference to the instance of ActionHelper
return helper.DoAction;
}
class ActionHelper
{
// Just for simplicity, make it public. I don't know if the
// C# compiler really does.
public int counter;
public void DoAction()
{
Console.WriteLine(counter);
counter++;
}
}
}
If you capture variables declared in a loop, you'd end up with a new instance of ActionHelper for each iteration of the loop - so you'd effectively capture different "instances" of the variables.
It gets more complicated when you capture variables from different scopes... let me know if you really want that sort of level of detail, or you could just write some code, decompile it in Reflector and follow it through :)
Note how:
There's no boxing involved
There are no pointers involved, or any other unsafe code
EDIT: Here's an example of two delegates sharing a variable. One delegate shows the current value of counter, the other increments it:
using System;
class Program
{
static void Main(string[] args)
{
var tuple = CreateShowAndIncrementActions();
var show = tuple.Item1;
var increment = tuple.Item2;
show(); // Prints 0
show(); // Still prints 0
increment();
show(); // Now prints 1
}
static Tuple<Action, Action> CreateShowAndIncrementActions()
{
int counter = 0;
Action show = () => { Console.WriteLine(counter); };
Action increment = () => { counter++; };
return Tuple.Create(show, increment);
}
}
... and the expansion:
using System;
class Program
{
static void Main(string[] args)
{
var tuple = CreateShowAndIncrementActions();
var show = tuple.Item1;
var increment = tuple.Item2;
show(); // Prints 0
show(); // Still prints 0
increment();
show(); // Now prints 1
}
static Tuple<Action, Action> CreateShowAndIncrementActions()
{
ActionHelper helper = new ActionHelper();
helper.counter = 0;
Action show = helper.Show;
Action increment = helper.Increment;
return Tuple.Create(show, increment);
}
class ActionHelper
{
public int counter;
public void Show()
{
Console.WriteLine(counter);
}
public void Increment()
{
counter++;
}
}
}
Related
I have been reading some C# interview questions and found a permutation of a popular one about delegates the code of which puzzles me.
The question was:
Predict the output of the code below.
delegate void Iterator();
static void Main(string[] args)
{
List<Iterator> iterators = new List<Iterator>();
for (int i = 0; i < 15; i++)
{
iterators.Add(delegate { Console.WriteLine(i); });
}
foreach (var iterator in iterators)
{
iterator();
}
Console.Read();
}
The normal version of this question I've seen declares the i variable before the for loop, thus making it method-wide and from there it's easy to see why the output is "15" 15 times.
However when I debugged the code the i variable is out of scope in the foreach loop and does not exist, anymore. Yet, when I step into the iterator() method it exists for the Console.WriteLine(i) line.
This I cannot understand.
The compiler translates your code to the following code, this is why i variable is not out of scope.
private delegate void Iterator();
[CompilerGenerated]
private sealed class CompGenCls
{
public int i;
internal void CompGenFunc()
{
Console.WriteLine(i);
}
}
private static void Main(string[] args)
{
List<Iterator> iterators = new List<Iterator>();
CompGenCls obj = new CompGenCls();
obj.i = 0;
for (; obj.i < 15; obj.i++)
{
iterators.Add(obj.CompGenFunc);
}
foreach (Iterator item in iterators)
{
item();
}
Console.Read();
}
To put it very simply, closures allow you to encapsulate some
behaviour, pass it around like any other object, and still have access
to the context in which they were first declared. This allows you to
separate out control structures, logical operators etc from the
details of how they're going to be used. The ability to access the
original context is what separates closures from normal objects,
although closure implementations typically achieve this using normal
objects and compiler trickery.
In your example you've only actually declared a single i variable -
so that same i variable is captured by all the Action instances. The
result is the number 15 being printed on every line. o "fix" the code
to make it display the output most people would expect (i.e. 0 to 14)
we need to introduce an extra variable inside the loop:
delegate void Iterator();
static void Main(string[] args)
{
List<Iterator> iterators = new List<Iterator>();
for (int i = 0; i < 15; i++)
{
int copy = i;
iterators.Add(delegate { Console.WriteLine(copy); });
}
foreach (var iterator in iterators)
{
iterator();
}
Console.Read();
}
Each time we go through the loop we're said to get a different
instance of the copy variable - each Action captures a different
variable. This makes perfect sense if you look at what the compiler's
actually doing behind the scenes, but initially it flies in the face
of the intuition of most developers (including me).
via
I am just a beginner in the world of programming, thus I have a simple question. Is it possible to randomly execute functions? If so, how would you do it? It is just a curiosity based on a thread I've read in another forum. Basically, the discussion was on how to generate random events for a game, and they commented about a "hack" used in some languages (especially AS3). The hack is to treat functions as variables. Example:
//Make an array of the functions
public function makeEarthquake():void{}
public function causePlague():void{}
public function spaceZombieAttack():void{}
//select at random
var selection:uint = Math.random() * eventArrray.length;
//Call it
eventArray[selection]();
I hope this is clear. I will be happy with any answer that can explain how to randomly call methods. Thank you.
EDIT: Thank you guys, all the answers were helpful!!!
It's certainly possible. A direct way is to have a list or array of delegates:
In C# it looks like this: (In a basic console app)
class Program
{
// Create the functions:
static void Beep()
{
Console.Beep();
}
static void SayHello()
{
Console.WriteLine("Hello!");
}
// Create the function delegate:
private delegate void RandomFunction();
static void Main(string[] args)
{
// Create a list of these delegates:
List<RandomFunction> functions = new List<RandomFunction>();
// Add the functions to the list:
functions.Add(Beep);
functions.Add(SayHello);
// Make our randomizer:
Random rand = new Random();
// Call one:
functions[rand.Next(0, 2)](); // Random number either 0 or 1
// This is just here to stop the program
// from closing straight away should it say "Hello"
Console.ReadKey();
}
}
Getting these functions to have varying numbers of parameters takes a bit more effort, though.
You can have a List<Action> and randomly select from it.
class Program
{
static void Main(string[] args)
{
List<Action> actions = new List<Action>();
actions.Add(() => Program.MakeEarthquake());
actions.Add(() => Program.CausePlague());
actions.Add(() => Program.SpaceZombieAttack());
Random random = new Random();
int selectedAction = random.Next(0, actions.Count());
actions[selectedAction].Invoke();
}
static void MakeEarthquake()
{
Console.WriteLine("Earthquake");
}
static void CausePlague()
{
Console.WriteLine("Plague");
}
static void SpaceZombieAttack()
{
Console.WriteLine("Zombie attack");
}
}
You can create list of actions then choosing one the items inside the list randomly like below code
List<Action> actions = new List<Action>();
actions.Add(() => makeEarthquake());
actions.Add(() => causePlague());
actions.Add(() => spaceZombieAttack());
var random=new Random();
int rndNumber = random.Next(actions.Count);
actions[rndNumber].Invoke();
Why don't you pick a random number like usual, then use that number within a common function which in turn calls a function based on what you got?
public void DoRandomThing()
{
switch(new Random().Next(1,4))
{
case 1:
makeEarthquake();
break;
case 2:
causePlague();
break;
case 3:
spaceZombieAttack();
break;
}
}
I want to have a static (global) pool of calculators which are going to be accessed by a lot of different threads.
After some researching I found out that the elements of Arrays are threadsafe.
I thought that it would be good idea to store the diffrent calculators (amount unknown until runtime) in a static array (calculator[] calculators).
How do I ensure that only one calculator is being used by one calculator?
I read the whole msdn documentation so don't post "only" links please.
I have also thought about a bool array "locked" but I can't find a way to implement this threadsafe.
My code so far:
internal static class Calculators
{
private static Semaphore pool;
private static bool[] locked;
private static calcs[] neuralNetworks;
private static Thread[] threads;
internal static Calculators(){
int number = Globals.Number;
pool = new Semaphore(number, number);
locked = new bool[number];
calcs = new calcs[number];
threads = new Thread[number];
for (int index = 0; index < number; index++)
{
// all neuralNetworks are unlocked by default
locked[index] = false;
// generate one network per "countThreads"
calcs[index] = Globals.CalcObj;
// generate one thread for each neural network
threads[index] = new Thread(new ThreadStart());
}
}
private int WhichCalculators()
{
int index;
for (index = 0; index < countThreads; index++)
{
if (locked[index] == false)
{
locked[index] = true;
return index;
}
}
throw new Exception("Calculators was called, but there weren't any networks unused");
}
}
Code Update:
So should it work, if I call "WhichCalculator()" in this method?
private static void doStuff()
{
pool.WaitOne();
Monitor.Enter(thisLock);
try
{
int whichCalculator = WhichCalculator();
locked[whichCalculator] = true;
lock (calculators[whichCalculator])
{
Monitor.Exit(thisLock);
// do stuff
locked[whichCalculator] = false;
}
}
catch
{
Monitor.Exit(thisLock);
}
//Calculate();
pool.Release();
}
Question 2:
Am I right to assume, that the static constructor is going to be executed as soon as (but before) the first time this class or any member of it is going to be accessed?
Yes you have to use lock. But the array and every instance of calculator again.
If you can fill the array before you start the multithreaded section of your code you need not lock the array as well (only reading doesn't make problems due to the static content) but with resizing the array you need to lock every access to it (writing AND reading).
So your code could look like this:
Calculator calc = null;
lock(calculators)
{
calc = calculators[0];
}
lock(calc)
{
// ... do stuff
}
This way the array isn't longer locked then needed and you can lock the calculator itself.
You can lock your array. That would ensure that every array-operation is executed thread-safe.
To ensure, that each object is only used once at a time you can add a flag to it, like calculator.InUse. If you can't add a flag to the class, you can use an extension method.
The code snippet below exhibits a bug I was able to isolate from production code. The program will crash with a System.AccessViolationException.
My system configuration is Visual Studio 2013 on Windows 8.1 x64. To reproduce the bug, follow these steps in Visual Studio:
Create an empty Console Application
Replace the entire contents of Program.cs with the code below
Compile in Release mode, Any CPU
Start without debugging (CTRL + F5)
The program will crash immediately, displaying an error stack trace in the Console window.
I was not able to reduce the code any further, i.e. modifying any portion of the code will make the bug disappear.
Is there any way to tell the root cause of this bug? What would be a good workaround?
using System;
using System.Threading.Tasks;
namespace ParallelBugTest
{
class Program
{
private class Value
{
public double X;
}
private class Aggregator
{
private Value myval = new Value();
public void Add()
{
// use Min() instead of Max() -> bug disappears
myval.X = Math.Max(0, myval.X);
}
}
public static void Main(string[] args)
{
Parallel.For(0, 10000, Process);
}
private static void Process(int k)
{
Value[] V = new Value[10000];
Aggregator aggregator = new Aggregator();
for (int i = 0; i < V.Length; i++)
{
V[i] = new Value();
aggregator.Add();
}
}
}
}
Everything in your code is thread-safe, since there is no shared state between threads (each iteration has its own Aggregator and the array of Values and you're not using any static fields).
Even if your code wasn't thread-safe, it doesn't do anything unsafe (i.e. working directly with memory), which should be the only way to get AccessViolationException.
Because of that, I believe this is a bug in the CLR and you should report it (click on the "submit feedback" link after logging in).
Math.Max is not Thread-Safe. I guess Min is working because it is faster to calculate.
Locking the Max-Call works:
private static Object lockObj = new Object();
private class Value
{
public double X;
}
private class Aggregator
{
private Value myval = new Value();
public void Add()
{
// use Min() instead of Max() -> bug disappears
lock (lockObj)
{
myval.X = Math.Max(0, myval.X);
}
}
}
public static void Main(string[] args)
{
Parallel.For(0, 10000, Process);
}
private static void Process(int k)
{
Value[] V = new Value[10000];
Aggregator aggregator = new Aggregator();
for (int i = 0; i < V.Length; i++)
{
V[i] = new Value();
aggregator.Add();
}
}
Fast and easier way is just to use an ordinary iif:
public void Add()
{
// use Min() instead of Max() -> bug disappears
myval.X = myval.X > 0 ? myval.X : 0;
}
Is there any way to stop a running loop inside another method or insert a break statement dynamically in C#?
Thanks
Edit : I want to be able to dynamically intercept the method and insert a break to stop the loop when an event gets triggered in another function.I have several instances of the class and I want to stop the loop in each instance whenever required and manage all the instances. Consider multiple instances to be in a generic list
Example :
List<myclass> objlist=new List<myclass>();
foreach(myclass obj in objlist)
{
obj.loopingfunction().BreakLoop //or something like this (assuming that the loopingfunction is already called)
}
I need this because I want to break the loop once the user stores some huge amount of data.When the user imports the data,I get a event fired. But I cannot keep checking the database from multiple instances since it screws up sqlserver.
This is in an ASP.Net application.
If the whole thing is running in a single thread, it wouldn't make any sense. If the loop is running, then nothing else is running at the same time. If you're running a loop on another thread and the controlling method on another thread, you can either abort the loop thread completely or check a flag inside the loop to decide whether or not you should break and set the flag appropriately in the controlling method.
Update: make that function return a boolean value indicating whether you should break and use it in an "if" statement:
if (myFunctionShouldBreakLoop()) break;
Another option would be to raise a CancelEventArgs during every iteration of the loop. Probably not the most efficient, but another option nonetheless:
private void SomeMethod()
{
for (int i = 0; i <= 100000; i++)
{
Console.WriteLine(i);
if (LoopIncrement != null)
{
CancelEventArgs args = new CancelEventArgs();
LoopIncrement(null, args);
if (args.Cancel)
{
break;
}
}
}
And then elsewhere:
myObj.LoopIncrement += MyHandler;
private void MyHandler(object sender, CancelEventArgs e)
{
if(someCondition)
{
e.Cancel = true;
}
}
This way you can somewhat control the loop from outside....
Have the condition in a locked property.
private Boolean BreakCondition
{
get { lock(_LockObject) { return _BreakCondition; } }
set { lock(_LockObject) { _BreakCondition = value; } }
}
private Boolean _BreakCondition = false;
private Object _LockObject = new Object();
if (this.BreakCondition)
{
break;
}
How about using iterators, and yield magic to solve the problem.
Here is an article on infinite lists that might be useful
http://www.codethinked.com/post/2009/02/04/Infinite-Lists-With-C-Yield.aspx
class Program
{
static void Main(string[] args)
{
Predicate<int> when = i => i > 100 && Console.ReadKey().KeyChar.ToString() == "0";
foreach(var i in Numbers().BreakOn(when))
{
Console.WriteLine(i);
}
Console.ReadLine();
}
private static IEnumerable<int> Numbers()
{
var i = 0;
while(true)
{
yield return i++;
}
}
}
public static class Util
{
public static IEnumerable<int> BreakOn(this IEnumerable<int> sequence, Predicate<int> when)
{
foreach(int i in sequence)
{
if(when(i))
{
yield break;
}
yield return i;
}
}
}
I think you can use flag
bool stop = false;
for(int i=0;i<num;i++)
{
if(stop) break;
}
The short answer is: no. If you don't control the code, then you can't cause the loop to terminate.
If you do control the code, you could build in some sort of cooperation, but it sounds messy. Maybe you can elaborate on why?