14

Hi all I am trying to write and anonymous delegate. as the integer variable is shared among the delegate I need it to be the local instance of every delegate such that rs[0] always gets nics[0], rs[1] always gets nics[1] and so on... how will I achieve this.

for (int i = 0; i < nics.Count; i++)
{
    rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
    {
        return GetNetworkUtilization(nics[i]);
    }));
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Abdul Khaliq
  • 2,423
  • 12
  • 40
  • 65
  • 6
    Be *extremely* careful about what you ask for. Do you want your first closure to always get the value in nics[0] *at the time the delegate is invoked*, or do you want the closure to get the value that happened to be in nics[0] *at the time the delegate was created*? Those are two different things; nics[0] is a variable, so its value can change over time. Do you want the closure to see that change, or ignore that change? – Eric Lippert Nov 18 '09 at 16:34

3 Answers3

23

Make a local copy of i:

   for (int i = 0; i < nics.Count; i++)
   {
         int j = i;
         rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
         {
            return GetNetworkUtilization(nics[j]);
          }));
    }

The Beauty of Closures

bruno conde
  • 47,767
  • 15
  • 98
  • 117
6

Use a local to get a different value per iteration

for (int i = 0; i < nics.Count; i++)
   {
         int localI = i;
         rs[i] = new RollingSeries(monitor, new RollingSeries.NextValueDelegate(delegate()
         {
            return GetNetworkUtilization(nics[localI]);
          }));
    }
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
4

Put int j = i inside your loop and refer to j within the lambda expression.

If you are curious about why this happens, here is an MSDN blog entry containing a detailed technical explanation: Closing over the loop variable considered harmful

Heinzi
  • 167,459
  • 57
  • 363
  • 519