Exercises in this lecture   Go to the notes, in which this exercise belongs -- Keyboard shortcut: 'u'   Alphabetic index   Course home   

Exercise solution:
How local are local variables and formal parameters?


Here is the program (again):

using System;
public class Application { 

  public delegate double NumericFunction(double d);   
  static double factor = 4.0;

  public static NumericFunction MakeMultiplier(double factor){
     return delegate(double input){return input * factor;};
  }

  public static void Main(){
    NumericFunction f = MakeMultiplier(3.0); 
    double input = 5.0;

    Console.WriteLine("factor = {0}", factor);
    Console.WriteLine("input = {0}", input);
    Console.WriteLine("f is a generated function which multiplies its input with factor");
    Console.WriteLine("f(input) = input * factor = {0}", f(input));
  }
}

and its output:

factor = 4
input = 5
f is a generated function which multiplies its input with factor
f(input) = input * factor = 15

There are obviously two variables called factor in this program: (1) The static (global) variable factor, and the formal parameter factor of MakeMultiplier.

According to normal wisdom, the formal parameter factor is a local variable which only exists during the call of MakeMultiplier.

In addition, it is common wisdom that free names of functions are bound in the context of the function definitions, not in the context of funcion calls. Thus, in the the anonymous function

  delegate(double input){return input * factor;}

the free name factor is bound to the formal parameter of MakeMultiplier, and never to more global variables of the same name.

(A free name in a function is a name which is used in the function, but not defined in the function).

These observations contradict each other.

In C#, local variables of a function may survive the activation of the function. Thus, the the formal parameter factor (bound to 3.0) is available in the WriteLine statements of Main. In C#, this is often called captured outer variables. The function

  delegate(double input){return input * factor;}

gives rise to a closure, which holds on to its free names (here the variable factor).