#1,186 – Capturing a foreach Iteration Variable in a Lambda Expression

If you capture a for loop iteration variable in a lambda expression, the value of the variable that the expression uses will be whatever the final value of the iteration variable is when the loop completes.

Capturing the iteration variable in a foreach loop works differently.  When you capture the iteration variable in a foreach loop, the lambda expression has a copy of the iteration variable with the value that it had at the time that it was captured.

            int[] primes = { 2, 3, 5, 7, 11, 13 };
            List<Action> dels = new List<Action>();

            // Capture foreach iteration variable
            foreach (int p in primes)
                dels.Add(() => Console.WriteLine(p));

            foreach (Action a in dels)
                a();

1186-001

#1,185 – Managing using Directives, part II

You can add missing using directives by using the Resolve command.  You can also clean up the current list of using directives in a file, removing the ones that are no longer needed.

You can remove unneeded using directives by clicking anywhere within a file and selecting Organize Usings | Remove Unused Usings.

In the example below, we start out with 20 using directives at the top of the file.

1159-001

We then select Remove Unused Usings.

1159-002

After we execute this command, we’re left with only four using directives at the top of the file.

1159-003

#1,184 – Managing using Directives, part I

As you write code, Visual Studio will let you know that you’ve used an identifier that it doesn’t know by marking it with a red squiggly underline.  Below, we’ve started creating a class that derives from Shape.  But Visual Studio tells us that it doesn’t know about Shape.

1158-001

The easiest way to resolve this is to try right-clicking on the unknown identifer and selecting the Resolve entry.  Visual Studio will give you a list of namespaces that it can find the identifier in.  You can then select one of these options and Visual Studio will add the relevant using directive.

1158-002

 

1158-003

Note that this will only work if the identifer is valid somewhere within the assemblies that your project has referenced.  If you have correctly spelled an identifer and the Resolve option does not appear, you will need to add a reference to the assembly where the identifier in question is defined.

 

 

#1,183 – How to Correctly Capture a for Loop Variable in a Lambda Expression

If you directly capture a for loop variable within a lambda expression, the value used when executing the expression will typically be the value of the variable at the time that the loop exits.  If you instead want to capture a variable whose value is the value of the for loop variable while the loop is executing, you can use a local variable.

            Action[] dels = new Action[3];

            // How to correctly capture for loop variable
            for (int i = 0; i < 3; i++)
            {
                int iLocal = i;
                dels[i] = () => Console.WriteLine(iLocal + 1);
            }

            // Prints 1/2/3
            foreach (Action d in dels)
                d();

1183-001

#1,182 – Capturing a for Loop Variable in a Lambda Expression

If you capture a variable in a lambda expression that is declared within the initializer of a for loop, the results may not be what you expect.  Recall that the value of a captured variable is evaluated when a delegate is invoked, rather than when it is assigned.  If you therefore invoke the delegate after all iterations of the loop have executed, the value of the captured variable will be whatever the final value of the variable was.

Below, notice that the same value is displayed during each invocation of the delegate.

            Action[] dels = new Action[3];

            for (int i = 0; i < 3; i++)
                dels[i] = () => Console.WriteLine(i + 1);

            // Prints 4/4/4, rather than 1/2/3
            foreach (Action d in dels)
                d();

1182-001

#1,181 – Instantiating an Object within a Lambda Expression

You can create instance of objects within lambda expression.  You can also optionally return that instance as the result of the expression.

            // Delegate set to dog-creating lambda
            Func<string,Dog> dogCreator = s => {
                Dog d = new Dog(s);
                d.Bark();
                return d;
            };

            Dog d1 = dogCreator("Lassie");

            Thread.Sleep(3000);  // wait 3 secs

            Dog d2 = dogCreator("Kirby");

            // Dump out creation time info
            Console.WriteLine(d1);
            Console.WriteLine(d2);

1181-001

#1,180 – Lambda Expressions Can Modify Captured Variables

When a variable is captured by inclusion in a lambda expression, the expression is free to modify the value of the captured variable, assuming that the variable is modifiable in the scope in which the lambda is defined.

            int localVariable = 10;

            Action<int> adder = i => localVariable += i;

            Console.WriteLine(string.Format("local at start: {0}", localVariable));
            adder(5);
            Console.WriteLine(string.Format("after calling adder, local: {0}", localVariable));

1180-001

Follow

Get every new post delivered to your Inbox.

Join 449 other followers